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.ui;
1972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
20d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport java.io.IOException;
21d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport java.util.ArrayList;
22d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport java.util.Collection;
23d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport java.util.HashMap;
24d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport java.util.Map;
25d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport java.util.concurrent.ConcurrentHashMap;
2672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
2772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.app.Activity;
2872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.app.AlertDialog;
2972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.content.ContentUris;
3072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.content.Context;
3172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.content.DialogInterface;
3272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.content.DialogInterface.OnCancelListener;
3372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.content.DialogInterface.OnClickListener;
34d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport android.content.Intent;
3572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.content.res.Resources;
3672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.database.Cursor;
37d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport android.database.sqlite.SqliteWrapper;
3815057746d75afb5fec583f30064b382c18403608Tom Taylorimport android.media.CamcorderProfile;
3972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.media.RingtoneManager;
4072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.net.Uri;
41ebea1f24c246b8fa972ab9cbe52e6f506c5fc825Tom Taylorimport android.os.Environment;
4272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.os.Handler;
4315057746d75afb5fec583f30064b382c18403608Tom Taylorimport android.provider.MediaStore;
44f7e8281a223af6228e6399055a6197a1edd9bc3aTom Taylorimport android.provider.Telephony.Mms;
45f7e8281a223af6228e6399055a6197a1edd9bc3aTom Taylorimport android.provider.Telephony.Sms;
4672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.telephony.PhoneNumberUtils;
4772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.text.TextUtils;
4872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.text.format.DateUtils;
4972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.text.format.Time;
5072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.text.style.URLSpan;
5172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.util.Log;
521224b6560c48e146ee304f9c807296f6c22cdefbTom Taylorimport android.widget.Toast;
5372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
54d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.android.mms.LogTag;
55d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.android.mms.MmsApp;
56d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.android.mms.MmsConfig;
57d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.android.mms.R;
58d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.android.mms.TempFileProvider;
59d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.android.mms.data.WorkingMessage;
60d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.android.mms.model.MediaModel;
61d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.android.mms.model.SlideModel;
62d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.android.mms.model.SlideshowModel;
63d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.android.mms.transaction.MmsMessageSender;
64d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.android.mms.util.AddressUtils;
65d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.google.android.mms.ContentType;
66d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.google.android.mms.MmsException;
67d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.google.android.mms.pdu.CharacterSets;
68d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.google.android.mms.pdu.EncodedStringValue;
69d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.google.android.mms.pdu.MultimediaMessagePdu;
70d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.google.android.mms.pdu.NotificationInd;
71d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.google.android.mms.pdu.PduBody;
72d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.google.android.mms.pdu.PduHeaders;
73d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.google.android.mms.pdu.PduPart;
74d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.google.android.mms.pdu.PduPersister;
75d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.google.android.mms.pdu.RetrieveConf;
76d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.google.android.mms.pdu.SendReq;
7772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
7872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project/**
7972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * An utility class for managing messages.
8072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project */
8172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectpublic class MessageUtils {
8272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    interface ResizeImageResultCallback {
83edd39351defc331fc268a6ed88338f64fe6f17cfTom Taylor        void onResizeResult(PduPart part, boolean append);
8472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
8572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
869242286c35743422051d439d7460cd0a1426899cWei Huang    private static final String TAG = LogTag.TAG;
8772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static String sLocalNumber;
883c307cabb5bd96ed174930ebf17f533bf2a79de7Tom Taylor    private static String[] sNoSubjectStrings;
8972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
9072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    // Cache of both groups of space-separated ids to their full
9172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    // comma-separated display names, as well as individual ids to
9272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    // display names.
9372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    // TODO: is it possible for canonical address ID keys to be
9472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    // re-used?  SQLite does reuse IDs on NULL id_ insert, but does
9572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    // anything ever delete from the mmssms.db canonical_addresses
9672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    // table?  Nothing that I could find.
9772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static final Map<String, String> sRecipientAddress =
9872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            new ConcurrentHashMap<String, String>(20 /* initial capacity */);
9972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
100bd9d9bc46fb988e69aa92a1ef0b00d20c8be593dTom Taylor    // When we pass a video record duration to the video recorder, use one of these values.
101bd9d9bc46fb988e69aa92a1ef0b00d20c8be593dTom Taylor    private static final int[] sVideoDuration =
102bd9d9bc46fb988e69aa92a1ef0b00d20c8be593dTom Taylor            new int[] {0, 5, 10, 15, 20, 30, 40, 50, 60, 90, 120};
10378f81825431c8c52cad57bc4a363747533a701abWei Huang
10478f81825431c8c52cad57bc4a363747533a701abWei Huang    /**
10578f81825431c8c52cad57bc4a363747533a701abWei Huang     * MMS address parsing data structures
10678f81825431c8c52cad57bc4a363747533a701abWei Huang     */
10778f81825431c8c52cad57bc4a363747533a701abWei Huang    // allowable phone number separators
10878f81825431c8c52cad57bc4a363747533a701abWei Huang    private static final char[] NUMERIC_CHARS_SUGAR = {
10978f81825431c8c52cad57bc4a363747533a701abWei Huang        '-', '.', ',', '(', ')', ' ', '/', '\\', '*', '#', '+'
11078f81825431c8c52cad57bc4a363747533a701abWei Huang    };
11178f81825431c8c52cad57bc4a363747533a701abWei Huang
11278f81825431c8c52cad57bc4a363747533a701abWei Huang    private static HashMap numericSugarMap = new HashMap (NUMERIC_CHARS_SUGAR.length);
11378f81825431c8c52cad57bc4a363747533a701abWei Huang
11478f81825431c8c52cad57bc4a363747533a701abWei Huang    static {
11578f81825431c8c52cad57bc4a363747533a701abWei Huang        for (int i = 0; i < NUMERIC_CHARS_SUGAR.length; i++) {
11678f81825431c8c52cad57bc4a363747533a701abWei Huang            numericSugarMap.put(NUMERIC_CHARS_SUGAR[i], NUMERIC_CHARS_SUGAR[i]);
11778f81825431c8c52cad57bc4a363747533a701abWei Huang        }
11878f81825431c8c52cad57bc4a363747533a701abWei Huang    }
11978f81825431c8c52cad57bc4a363747533a701abWei Huang
12078f81825431c8c52cad57bc4a363747533a701abWei Huang
12172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private MessageUtils() {
12272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // Forbidden being instantiated.
12372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
12472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
1253c307cabb5bd96ed174930ebf17f533bf2a79de7Tom Taylor    /**
1263c307cabb5bd96ed174930ebf17f533bf2a79de7Tom Taylor     * cleanseMmsSubject will take a subject that's says, "<Subject: no subject>", and return
1273c307cabb5bd96ed174930ebf17f533bf2a79de7Tom Taylor     * a null string. Otherwise it will return the original subject string.
1283c307cabb5bd96ed174930ebf17f533bf2a79de7Tom Taylor     * @param context a regular context so the function can grab string resources
1293c307cabb5bd96ed174930ebf17f533bf2a79de7Tom Taylor     * @param subject the raw subject
1303c307cabb5bd96ed174930ebf17f533bf2a79de7Tom Taylor     * @return
1313c307cabb5bd96ed174930ebf17f533bf2a79de7Tom Taylor     */
1323c307cabb5bd96ed174930ebf17f533bf2a79de7Tom Taylor    public static String cleanseMmsSubject(Context context, String subject) {
1333c307cabb5bd96ed174930ebf17f533bf2a79de7Tom Taylor        if (TextUtils.isEmpty(subject)) {
1343c307cabb5bd96ed174930ebf17f533bf2a79de7Tom Taylor            return subject;
1353c307cabb5bd96ed174930ebf17f533bf2a79de7Tom Taylor        }
1363c307cabb5bd96ed174930ebf17f533bf2a79de7Tom Taylor        if (sNoSubjectStrings == null) {
1373c307cabb5bd96ed174930ebf17f533bf2a79de7Tom Taylor            sNoSubjectStrings =
1383c307cabb5bd96ed174930ebf17f533bf2a79de7Tom Taylor                    context.getResources().getStringArray(R.array.empty_subject_strings);
1393c307cabb5bd96ed174930ebf17f533bf2a79de7Tom Taylor
1403c307cabb5bd96ed174930ebf17f533bf2a79de7Tom Taylor        }
1413c307cabb5bd96ed174930ebf17f533bf2a79de7Tom Taylor        final int len = sNoSubjectStrings.length;
1423c307cabb5bd96ed174930ebf17f533bf2a79de7Tom Taylor        for (int i = 0; i < len; i++) {
1433c307cabb5bd96ed174930ebf17f533bf2a79de7Tom Taylor            if (subject.equalsIgnoreCase(sNoSubjectStrings[i])) {
1443c307cabb5bd96ed174930ebf17f533bf2a79de7Tom Taylor                return null;
1453c307cabb5bd96ed174930ebf17f533bf2a79de7Tom Taylor            }
1463c307cabb5bd96ed174930ebf17f533bf2a79de7Tom Taylor        }
1473c307cabb5bd96ed174930ebf17f533bf2a79de7Tom Taylor        return subject;
1483c307cabb5bd96ed174930ebf17f533bf2a79de7Tom Taylor    }
1493c307cabb5bd96ed174930ebf17f533bf2a79de7Tom Taylor
15072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    public static String getMessageDetails(Context context, Cursor cursor, int size) {
15172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (cursor == null) {
15272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            return null;
15372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
15472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
15572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if ("mms".equals(cursor.getString(MessageListAdapter.COLUMN_MSG_TYPE))) {
15672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            int type = cursor.getInt(MessageListAdapter.COLUMN_MMS_MESSAGE_TYPE);
15772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            switch (type) {
15872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                case PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND:
15972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    return getNotificationIndDetails(context, cursor);
16072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                case PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF:
16172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                case PduHeaders.MESSAGE_TYPE_SEND_REQ:
16272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    return getMultimediaMessageDetails(context, cursor, size);
16372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                default:
16472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    Log.w(TAG, "No details could be retrieved.");
16572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    return "";
16672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
16772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        } else {
16872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            return getTextMessageDetails(context, cursor);
16972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
17072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
17172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
17272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static String getNotificationIndDetails(Context context, Cursor cursor) {
17372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        StringBuilder details = new StringBuilder();
17472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        Resources res = context.getResources();
17572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
17672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        long id = cursor.getLong(MessageListAdapter.COLUMN_ID);
17772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        Uri uri = ContentUris.withAppendedId(Mms.CONTENT_URI, id);
17872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        NotificationInd nInd;
17972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
18072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        try {
18172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            nInd = (NotificationInd) PduPersister.getPduPersister(
18272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    context).load(uri);
18372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        } catch (MmsException e) {
18472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            Log.e(TAG, "Failed to load the message: " + uri, e);
18572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            return context.getResources().getString(R.string.cannot_get_details);
18672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
18772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
18872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // Message Type: Mms Notification.
18972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        details.append(res.getString(R.string.message_type_label));
19072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        details.append(res.getString(R.string.multimedia_notification));
19172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
19272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // From: ***
19372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        String from = extractEncStr(context, nInd.getFrom());
19472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        details.append('\n');
19572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        details.append(res.getString(R.string.from_label));
19672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        details.append(!TextUtils.isEmpty(from)? from:
19772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                 res.getString(R.string.hidden_sender_address));
19872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
19972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // Date: ***
20072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        details.append('\n');
20172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        details.append(res.getString(
20272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                R.string.expire_on,
20372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                MessageUtils.formatTimeStampString(
20472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                        context, nInd.getExpiry() * 1000L, true)));
20572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
20672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // Subject: ***
20772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        details.append('\n');
20872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        details.append(res.getString(R.string.subject_label));
20972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
21072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        EncodedStringValue subject = nInd.getSubject();
21172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (subject != null) {
21272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            details.append(subject.getString());
21372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
21472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
21572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // Message class: Personal/Advertisement/Infomational/Auto
21672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        details.append('\n');
21772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        details.append(res.getString(R.string.message_class_label));
21872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        details.append(new String(nInd.getMessageClass()));
21972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
22072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // Message size: *** KB
22172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        details.append('\n');
22272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        details.append(res.getString(R.string.message_size_label));
22372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        details.append(String.valueOf((nInd.getMessageSize() + 1023) / 1024));
22472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        details.append(context.getString(R.string.kilobyte));
22572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
22672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        return details.toString();
22772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
22872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
22972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static String getMultimediaMessageDetails(
23072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            Context context, Cursor cursor, int size) {
23172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        int type = cursor.getInt(MessageListAdapter.COLUMN_MMS_MESSAGE_TYPE);
23272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (type == PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND) {
23372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            return getNotificationIndDetails(context, cursor);
23472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
23572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
23672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        StringBuilder details = new StringBuilder();
23772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        Resources res = context.getResources();
23872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
23972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        long id = cursor.getLong(MessageListAdapter.COLUMN_ID);
24072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        Uri uri = ContentUris.withAppendedId(Mms.CONTENT_URI, id);
24172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        MultimediaMessagePdu msg;
24272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
24372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        try {
24472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            msg = (MultimediaMessagePdu) PduPersister.getPduPersister(
24572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    context).load(uri);
24672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        } catch (MmsException e) {
24772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            Log.e(TAG, "Failed to load the message: " + uri, e);
24872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            return context.getResources().getString(R.string.cannot_get_details);
24972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
25072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
25172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // Message Type: Text message.
25272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        details.append(res.getString(R.string.message_type_label));
25372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        details.append(res.getString(R.string.multimedia_message));
25472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
25572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (msg instanceof RetrieveConf) {
25672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            // From: ***
25772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            String from = extractEncStr(context, ((RetrieveConf) msg).getFrom());
25872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            details.append('\n');
25972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            details.append(res.getString(R.string.from_label));
26072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            details.append(!TextUtils.isEmpty(from)? from:
26172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                  res.getString(R.string.hidden_sender_address));
26272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
26372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
26472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // To: ***
26572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        details.append('\n');
26672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        details.append(res.getString(R.string.to_address_label));
26772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        EncodedStringValue[] to = msg.getTo();
26872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (to != null) {
26972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            details.append(EncodedStringValue.concat(to));
27072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
27172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        else {
27272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            Log.w(TAG, "recipient list is empty!");
27372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
2749c5e0566f91c7622a7cf9d53a6a84c56ed4139c1Tom Taylor
27572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
27672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // Bcc: ***
27772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (msg instanceof SendReq) {
27872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            EncodedStringValue[] values = ((SendReq) msg).getBcc();
27972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            if ((values != null) && (values.length > 0)) {
28072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                details.append('\n');
28172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                details.append(res.getString(R.string.bcc_label));
28272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                details.append(EncodedStringValue.concat(values));
28372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
28472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
28572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
28672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // Date: ***
28772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        details.append('\n');
28872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        int msgBox = cursor.getInt(MessageListAdapter.COLUMN_MMS_MESSAGE_BOX);
28972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (msgBox == Mms.MESSAGE_BOX_DRAFTS) {
29072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            details.append(res.getString(R.string.saved_label));
29172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        } else if (msgBox == Mms.MESSAGE_BOX_INBOX) {
29272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            details.append(res.getString(R.string.received_label));
29372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        } else {
29472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            details.append(res.getString(R.string.sent_label));
29572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
29672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
29772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        details.append(MessageUtils.formatTimeStampString(
29872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                context, msg.getDate() * 1000L, true));
29972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
30072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // Subject: ***
30172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        details.append('\n');
30272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        details.append(res.getString(R.string.subject_label));
30372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
30472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        EncodedStringValue subject = msg.getSubject();
30572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (subject != null) {
30672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            String subStr = subject.getString();
30772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            // Message size should include size of subject.
30872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            size += subStr.length();
30972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            details.append(subStr);
31072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
31172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
31272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // Priority: High/Normal/Low
31372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        details.append('\n');
31472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        details.append(res.getString(R.string.priority_label));
31572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        details.append(getPriorityDescription(context, msg.getPriority()));
31672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
31772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // Message size: *** KB
31872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        details.append('\n');
31972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        details.append(res.getString(R.string.message_size_label));
32072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        details.append((size - 1)/1000 + 1);
32172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        details.append(" KB");
32272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
32372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        return details.toString();
32472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
32572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
32672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static String getTextMessageDetails(Context context, Cursor cursor) {
327b3217a6ddcd9455968de7078bfbc0a901b4ff705Tom Taylor        Log.d(TAG, "getTextMessageDetails");
328b3217a6ddcd9455968de7078bfbc0a901b4ff705Tom Taylor
32972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        StringBuilder details = new StringBuilder();
33072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        Resources res = context.getResources();
33172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
33272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // Message Type: Text message.
33372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        details.append(res.getString(R.string.message_type_label));
33472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        details.append(res.getString(R.string.text_message));
33572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
33672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // Address: ***
33772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        details.append('\n');
33872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        int smsType = cursor.getInt(MessageListAdapter.COLUMN_SMS_TYPE);
33972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (Sms.isOutgoingFolder(smsType)) {
34072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            details.append(res.getString(R.string.to_address_label));
34172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        } else {
34272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            details.append(res.getString(R.string.from_label));
34372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
34472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        details.append(cursor.getString(MessageListAdapter.COLUMN_SMS_ADDRESS));
34572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
34654711acb7191269e0a4723320bd74f29dd2c9223Fredrik Roubert        // Sent: ***
34754711acb7191269e0a4723320bd74f29dd2c9223Fredrik Roubert        if (smsType == Sms.MESSAGE_TYPE_INBOX) {
34854711acb7191269e0a4723320bd74f29dd2c9223Fredrik Roubert            long date_sent = cursor.getLong(MessageListAdapter.COLUMN_SMS_DATE_SENT);
34954711acb7191269e0a4723320bd74f29dd2c9223Fredrik Roubert            if (date_sent > 0) {
35054711acb7191269e0a4723320bd74f29dd2c9223Fredrik Roubert                details.append('\n');
35154711acb7191269e0a4723320bd74f29dd2c9223Fredrik Roubert                details.append(res.getString(R.string.sent_label));
35254711acb7191269e0a4723320bd74f29dd2c9223Fredrik Roubert                details.append(MessageUtils.formatTimeStampString(context, date_sent, true));
35354711acb7191269e0a4723320bd74f29dd2c9223Fredrik Roubert            }
35454711acb7191269e0a4723320bd74f29dd2c9223Fredrik Roubert        }
35554711acb7191269e0a4723320bd74f29dd2c9223Fredrik Roubert
35654711acb7191269e0a4723320bd74f29dd2c9223Fredrik Roubert        // Received: ***
35772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        details.append('\n');
35872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (smsType == Sms.MESSAGE_TYPE_DRAFT) {
35972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            details.append(res.getString(R.string.saved_label));
36072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        } else if (smsType == Sms.MESSAGE_TYPE_INBOX) {
36172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            details.append(res.getString(R.string.received_label));
36272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        } else {
36372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            details.append(res.getString(R.string.sent_label));
36472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
36572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
36672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        long date = cursor.getLong(MessageListAdapter.COLUMN_SMS_DATE);
36772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        details.append(MessageUtils.formatTimeStampString(context, date, true));
36872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
369831b1232edf7f01b9d31322083ad0180b2b375b9Tom Taylor        // Delivered: ***
370831b1232edf7f01b9d31322083ad0180b2b375b9Tom Taylor        if (smsType == Sms.MESSAGE_TYPE_SENT) {
371831b1232edf7f01b9d31322083ad0180b2b375b9Tom Taylor            // For sent messages with delivery reports, we stick the delivery time in the
372831b1232edf7f01b9d31322083ad0180b2b375b9Tom Taylor            // date_sent column (see MessageStatusReceiver).
373831b1232edf7f01b9d31322083ad0180b2b375b9Tom Taylor            long dateDelivered = cursor.getLong(MessageListAdapter.COLUMN_SMS_DATE_SENT);
374831b1232edf7f01b9d31322083ad0180b2b375b9Tom Taylor            if (dateDelivered > 0) {
375831b1232edf7f01b9d31322083ad0180b2b375b9Tom Taylor                details.append('\n');
376831b1232edf7f01b9d31322083ad0180b2b375b9Tom Taylor                details.append(res.getString(R.string.delivered_label));
377831b1232edf7f01b9d31322083ad0180b2b375b9Tom Taylor                details.append(MessageUtils.formatTimeStampString(context, dateDelivered, true));
378831b1232edf7f01b9d31322083ad0180b2b375b9Tom Taylor            }
379831b1232edf7f01b9d31322083ad0180b2b375b9Tom Taylor        }
380831b1232edf7f01b9d31322083ad0180b2b375b9Tom Taylor
381161375d2c4eff31add607fc0befa5c781c6fd7f1Tom Taylor        // Error code: ***
382161375d2c4eff31add607fc0befa5c781c6fd7f1Tom Taylor        int errorCode = cursor.getInt(MessageListAdapter.COLUMN_SMS_ERROR_CODE);
383161375d2c4eff31add607fc0befa5c781c6fd7f1Tom Taylor        if (errorCode != 0) {
384161375d2c4eff31add607fc0befa5c781c6fd7f1Tom Taylor            details.append('\n')
385161375d2c4eff31add607fc0befa5c781c6fd7f1Tom Taylor                .append(res.getString(R.string.error_code_label))
386161375d2c4eff31add607fc0befa5c781c6fd7f1Tom Taylor                .append(errorCode);
387161375d2c4eff31add607fc0befa5c781c6fd7f1Tom Taylor        }
388161375d2c4eff31add607fc0befa5c781c6fd7f1Tom Taylor
38972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        return details.toString();
39072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
39172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
39272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    static private String getPriorityDescription(Context context, int PriorityValue) {
39372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        Resources res = context.getResources();
39472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        switch(PriorityValue) {
39572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            case PduHeaders.PRIORITY_HIGH:
39672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                return res.getString(R.string.priority_high);
39772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            case PduHeaders.PRIORITY_LOW:
39872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                return res.getString(R.string.priority_low);
39972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            case PduHeaders.PRIORITY_NORMAL:
40072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            default:
40172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                return res.getString(R.string.priority_normal);
40272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
40372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
40472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
40572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    public static int getAttachmentType(SlideshowModel model) {
40672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (model == null) {
407fbcd6a7287afd459fee2521bfaf2d4f70668c85aTom Taylor            return MessageItem.ATTACHMENT_TYPE_NOT_LOADED;
40872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
40972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
41072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        int numberOfSlides = model.size();
41172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (numberOfSlides > 1) {
412b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick            return WorkingMessage.SLIDESHOW;
41372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        } else if (numberOfSlides == 1) {
41472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            // Only one slide in the slide-show.
41572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            SlideModel slide = model.get(0);
41672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            if (slide.hasVideo()) {
417b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick                return WorkingMessage.VIDEO;
41872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
41972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
42072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            if (slide.hasAudio() && slide.hasImage()) {
421b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick                return WorkingMessage.SLIDESHOW;
42272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
42372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
42472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            if (slide.hasAudio()) {
425b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick                return WorkingMessage.AUDIO;
42672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
42772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
42872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            if (slide.hasImage()) {
429b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick                return WorkingMessage.IMAGE;
43072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
43172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
43272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            if (slide.hasText()) {
433b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick                return WorkingMessage.TEXT;
43472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
43572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
43672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
437fbcd6a7287afd459fee2521bfaf2d4f70668c85aTom Taylor        return MessageItem.ATTACHMENT_TYPE_NOT_LOADED;
43872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
4399c5e0566f91c7622a7cf9d53a6a84c56ed4139c1Tom Taylor
44072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    public static String formatTimeStampString(Context context, long when) {
44172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        return formatTimeStampString(context, when, false);
44272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
44372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
44472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    public static String formatTimeStampString(Context context, long when, boolean fullFormat) {
44572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        Time then = new Time();
44672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        then.set(when);
44772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        Time now = new Time();
44872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        now.setToNow();
44972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
45072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // Basic settings for formatDateTime() we want for all cases.
45172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        int format_flags = DateUtils.FORMAT_NO_NOON_MIDNIGHT |
45272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                           DateUtils.FORMAT_ABBREV_ALL |
45372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                           DateUtils.FORMAT_CAP_AMPM;
454836945de572ac80fd6f6a7bf59036d4cce801410The Android Open Source Project
45572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // If the message is from a different year, show the date and year.
45672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (then.year != now.year) {
45772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            format_flags |= DateUtils.FORMAT_SHOW_YEAR | DateUtils.FORMAT_SHOW_DATE;
45872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        } else if (then.yearDay != now.yearDay) {
45972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            // If it is from a different day than today, show only the date.
46072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            format_flags |= DateUtils.FORMAT_SHOW_DATE;
46172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        } else {
46272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            // Otherwise, if the message is from today, show the time.
46372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            format_flags |= DateUtils.FORMAT_SHOW_TIME;
46472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
46572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
466836945de572ac80fd6f6a7bf59036d4cce801410The Android Open Source Project        // If the caller has asked for full details, make sure to show the date
467836945de572ac80fd6f6a7bf59036d4cce801410The Android Open Source Project        // and time no matter what we've determined above (but still make showing
468836945de572ac80fd6f6a7bf59036d4cce801410The Android Open Source Project        // the year only happen if it is a different year from today).
469836945de572ac80fd6f6a7bf59036d4cce801410The Android Open Source Project        if (fullFormat) {
470836945de572ac80fd6f6a7bf59036d4cce801410The Android Open Source Project            format_flags |= (DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_TIME);
471836945de572ac80fd6f6a7bf59036d4cce801410The Android Open Source Project        }
472836945de572ac80fd6f6a7bf59036d4cce801410The Android Open Source Project
47372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        return DateUtils.formatDateTime(context, when, format_flags);
47472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
47572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
476b8eae066a7ba60722de07300bf990d519f5c81d8Tom Taylor    public static void selectAudio(Activity activity, int requestCode) {
477b8eae066a7ba60722de07300bf990d519f5c81d8Tom Taylor        Intent intent = new Intent(RingtoneManager.ACTION_RINGTONE_PICKER);
478b8eae066a7ba60722de07300bf990d519f5c81d8Tom Taylor        intent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, false);
479b8eae066a7ba60722de07300bf990d519f5c81d8Tom Taylor        intent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_SILENT, false);
480b8eae066a7ba60722de07300bf990d519f5c81d8Tom Taylor        intent.putExtra(RingtoneManager.EXTRA_RINGTONE_INCLUDE_DRM, false);
481b8eae066a7ba60722de07300bf990d519f5c81d8Tom Taylor        intent.putExtra(RingtoneManager.EXTRA_RINGTONE_TITLE,
482b8eae066a7ba60722de07300bf990d519f5c81d8Tom Taylor                activity.getString(R.string.select_audio));
483b8eae066a7ba60722de07300bf990d519f5c81d8Tom Taylor        activity.startActivityForResult(intent, requestCode);
48472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
48572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
486b8eae066a7ba60722de07300bf990d519f5c81d8Tom Taylor    public static void recordSound(Activity activity, int requestCode, long sizeLimit) {
487b8eae066a7ba60722de07300bf990d519f5c81d8Tom Taylor        Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
488b8eae066a7ba60722de07300bf990d519f5c81d8Tom Taylor        intent.setType(ContentType.AUDIO_AMR);
489b8eae066a7ba60722de07300bf990d519f5c81d8Tom Taylor        intent.setClassName("com.android.soundrecorder",
490b8eae066a7ba60722de07300bf990d519f5c81d8Tom Taylor                "com.android.soundrecorder.SoundRecorder");
491b8eae066a7ba60722de07300bf990d519f5c81d8Tom Taylor        intent.putExtra(android.provider.MediaStore.Audio.Media.EXTRA_MAX_BYTES, sizeLimit);
492b8eae066a7ba60722de07300bf990d519f5c81d8Tom Taylor        activity.startActivityForResult(intent, requestCode);
49372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
49472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
495b8eae066a7ba60722de07300bf990d519f5c81d8Tom Taylor    public static void recordVideo(Activity activity, int requestCode, long sizeLimit) {
4968d095e452ac84b0a8e040fe4fdcdba45a44f4dc9Tom Taylor        // The video recorder can sometimes return a file that's larger than the max we
49765f27c5665a912deae21b285c399d41ee930bfe1Tom Taylor        // say we can handle. Try to handle that overshoot by specifying an 85% limit.
49865f27c5665a912deae21b285c399d41ee930bfe1Tom Taylor        sizeLimit *= .85F;
4998d095e452ac84b0a8e040fe4fdcdba45a44f4dc9Tom Taylor
500bd9d9bc46fb988e69aa92a1ef0b00d20c8be593dTom Taylor        int durationLimit = getVideoCaptureDurationLimit(sizeLimit);
5018d095e452ac84b0a8e040fe4fdcdba45a44f4dc9Tom Taylor
5028d095e452ac84b0a8e040fe4fdcdba45a44f4dc9Tom Taylor        if (Log.isLoggable(LogTag.APP, Log.VERBOSE)) {
5038d095e452ac84b0a8e040fe4fdcdba45a44f4dc9Tom Taylor            log("recordVideo: durationLimit: " + durationLimit +
5048d095e452ac84b0a8e040fe4fdcdba45a44f4dc9Tom Taylor                    " sizeLimit: " + sizeLimit);
5058d095e452ac84b0a8e040fe4fdcdba45a44f4dc9Tom Taylor        }
5068d095e452ac84b0a8e040fe4fdcdba45a44f4dc9Tom Taylor
507b8eae066a7ba60722de07300bf990d519f5c81d8Tom Taylor        Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
508b8eae066a7ba60722de07300bf990d519f5c81d8Tom Taylor        intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 0);
509b8eae066a7ba60722de07300bf990d519f5c81d8Tom Taylor        intent.putExtra("android.intent.extra.sizeLimit", sizeLimit);
510b8eae066a7ba60722de07300bf990d519f5c81d8Tom Taylor        intent.putExtra("android.intent.extra.durationLimit", durationLimit);
511b8eae066a7ba60722de07300bf990d519f5c81d8Tom Taylor        intent.putExtra(MediaStore.EXTRA_OUTPUT, TempFileProvider.SCRAP_CONTENT_URI);
512b8eae066a7ba60722de07300bf990d519f5c81d8Tom Taylor        activity.startActivityForResult(intent, requestCode);
513b8eae066a7ba60722de07300bf990d519f5c81d8Tom Taylor    }
51415057746d75afb5fec583f30064b382c18403608Tom Taylor
515b8eae066a7ba60722de07300bf990d519f5c81d8Tom Taylor    public static void capturePicture(Activity activity, int requestCode) {
516b8eae066a7ba60722de07300bf990d519f5c81d8Tom Taylor        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
517b8eae066a7ba60722de07300bf990d519f5c81d8Tom Taylor        intent.putExtra(MediaStore.EXTRA_OUTPUT, TempFileProvider.SCRAP_CONTENT_URI);
518b8eae066a7ba60722de07300bf990d519f5c81d8Tom Taylor        activity.startActivityForResult(intent, requestCode);
51915057746d75afb5fec583f30064b382c18403608Tom Taylor    }
52015057746d75afb5fec583f30064b382c18403608Tom Taylor
521bd9d9bc46fb988e69aa92a1ef0b00d20c8be593dTom Taylor    // Public for until tests
522bd9d9bc46fb988e69aa92a1ef0b00d20c8be593dTom Taylor    public static int getVideoCaptureDurationLimit(long bytesAvailable) {
5237a0d891850d3a57c6358f1a2c8798f4f84a47e7cTom Taylor        CamcorderProfile camcorder = CamcorderProfile.get(CamcorderProfile.QUALITY_LOW);
524bd9d9bc46fb988e69aa92a1ef0b00d20c8be593dTom Taylor        if (camcorder == null) {
525bd9d9bc46fb988e69aa92a1ef0b00d20c8be593dTom Taylor            return 0;
526bd9d9bc46fb988e69aa92a1ef0b00d20c8be593dTom Taylor        }
527bd9d9bc46fb988e69aa92a1ef0b00d20c8be593dTom Taylor        bytesAvailable *= 8;        // convert to bits
528bd9d9bc46fb988e69aa92a1ef0b00d20c8be593dTom Taylor        long seconds = bytesAvailable / (camcorder.audioBitRate + camcorder.videoBitRate);
529bd9d9bc46fb988e69aa92a1ef0b00d20c8be593dTom Taylor
530bd9d9bc46fb988e69aa92a1ef0b00d20c8be593dTom Taylor        // Find the best match for one of the fixed durations
531bd9d9bc46fb988e69aa92a1ef0b00d20c8be593dTom Taylor        for (int i = sVideoDuration.length - 1; i >= 0; i--) {
532bd9d9bc46fb988e69aa92a1ef0b00d20c8be593dTom Taylor            if (seconds >= sVideoDuration[i]) {
533bd9d9bc46fb988e69aa92a1ef0b00d20c8be593dTom Taylor                return sVideoDuration[i];
534bd9d9bc46fb988e69aa92a1ef0b00d20c8be593dTom Taylor            }
535bd9d9bc46fb988e69aa92a1ef0b00d20c8be593dTom Taylor        }
536bd9d9bc46fb988e69aa92a1ef0b00d20c8be593dTom Taylor        return 0;
53715057746d75afb5fec583f30064b382c18403608Tom Taylor    }
53815057746d75afb5fec583f30064b382c18403608Tom Taylor
53972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    public static void selectVideo(Context context, int requestCode) {
54002277c6b787e8e29ee22b1df745eb8549d3ff023Tom Taylor        selectMediaByType(context, requestCode, ContentType.VIDEO_UNSPECIFIED, true);
54172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
54272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
54372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    public static void selectImage(Context context, int requestCode) {
54402277c6b787e8e29ee22b1df745eb8549d3ff023Tom Taylor        selectMediaByType(context, requestCode, ContentType.IMAGE_UNSPECIFIED, false);
54572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
54672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
54772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static void selectMediaByType(
54802277c6b787e8e29ee22b1df745eb8549d3ff023Tom Taylor            Context context, int requestCode, String contentType, boolean localFilesOnly) {
54972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project         if (context instanceof Activity) {
55072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
55172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            Intent innerIntent = new Intent(Intent.ACTION_GET_CONTENT);
55272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
55372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            innerIntent.setType(contentType);
55402277c6b787e8e29ee22b1df745eb8549d3ff023Tom Taylor            if (localFilesOnly) {
55502277c6b787e8e29ee22b1df745eb8549d3ff023Tom Taylor                innerIntent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
55602277c6b787e8e29ee22b1df745eb8549d3ff023Tom Taylor            }
55772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
55872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            Intent wrapperIntent = Intent.createChooser(innerIntent, null);
55972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
56072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            ((Activity) context).startActivityForResult(wrapperIntent, requestCode);
56172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
56272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
56372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
56472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    public static void viewSimpleSlideshow(Context context, SlideshowModel slideshow) {
56572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (!slideshow.isSimple()) {
56672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            throw new IllegalArgumentException(
56772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    "viewSimpleSlideshow() called on a non-simple slideshow");
56872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
56972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        SlideModel slide = slideshow.get(0);
57072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        MediaModel mm = null;
57172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (slide.hasImage()) {
57272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            mm = slide.getImage();
57372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        } else if (slide.hasVideo()) {
57472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            mm = slide.getVideo();
57572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
5769c5e0566f91c7622a7cf9d53a6a84c56ed4139c1Tom Taylor
57772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        Intent intent = new Intent(Intent.ACTION_VIEW);
57872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
57970322de51cc7ef634c4b68b08b1c35b516fede77Todor Kalaydjiev        intent.putExtra("SingleItemOnly", true); // So we don't see "surrounding" images in Gallery
5809c5e0566f91c7622a7cf9d53a6a84c56ed4139c1Tom Taylor
5819c5e0566f91c7622a7cf9d53a6a84c56ed4139c1Tom Taylor        String contentType;
5820ecc26df09777835cfa8dbfd3c48ca7b7fa7f011Tom Taylor        contentType = mm.getContentType();
5839c5e0566f91c7622a7cf9d53a6a84c56ed4139c1Tom Taylor        intent.setDataAndType(mm.getUri(), contentType);
58472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        context.startActivity(intent);
58572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
5869c5e0566f91c7622a7cf9d53a6a84c56ed4139c1Tom Taylor
5873d8877fa3e07c019d1779793ca0081beca177b6aTom Taylor    public static void showErrorDialog(Activity activity,
58872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            String title, String message) {
5893d8877fa3e07c019d1779793ca0081beca177b6aTom Taylor        if (activity.isFinishing()) {
5903d8877fa3e07c019d1779793ca0081beca177b6aTom Taylor            return;
5913d8877fa3e07c019d1779793ca0081beca177b6aTom Taylor        }
5923d8877fa3e07c019d1779793ca0081beca177b6aTom Taylor        AlertDialog.Builder builder = new AlertDialog.Builder(activity);
59372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
59472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        builder.setIcon(R.drawable.ic_sms_mms_not_delivered);
59572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        builder.setTitle(title);
59672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        builder.setMessage(message);
59793b7a8bfa72a932843ecc7de4c9f9baec4ee2087Tom Taylor        builder.setPositiveButton(android.R.string.ok, new OnClickListener() {
5981009d4bf5ee9fd1f2523e530828de5babb78eb19Todor Kalaydjiev            @Override
59993b7a8bfa72a932843ecc7de4c9f9baec4ee2087Tom Taylor            public void onClick(DialogInterface dialog, int which) {
60093b7a8bfa72a932843ecc7de4c9f9baec4ee2087Tom Taylor                if (which == DialogInterface.BUTTON_POSITIVE) {
60193b7a8bfa72a932843ecc7de4c9f9baec4ee2087Tom Taylor                    dialog.dismiss();
60293b7a8bfa72a932843ecc7de4c9f9baec4ee2087Tom Taylor                }
60393b7a8bfa72a932843ecc7de4c9f9baec4ee2087Tom Taylor            }
60493b7a8bfa72a932843ecc7de4c9f9baec4ee2087Tom Taylor        });
60572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        builder.show();
60672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
60772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
608bd09a4b8c2d1f922f1459c4d7b61e7e87ed4ddf3The Android Open Source Project    /**
609bd09a4b8c2d1f922f1459c4d7b61e7e87ed4ddf3The Android Open Source Project     * The quality parameter which is used to compress JPEG images.
610bd09a4b8c2d1f922f1459c4d7b61e7e87ed4ddf3The Android Open Source Project     */
6118c86a52a2c13083a25761256ab0dfc416260c162Tom Taylor    public static final int IMAGE_COMPRESSION_QUALITY = 95;
6129242286c35743422051d439d7460cd0a1426899cWei Huang    /**
6139242286c35743422051d439d7460cd0a1426899cWei Huang     * The minimum quality parameter which is used to compress JPEG images.
6149242286c35743422051d439d7460cd0a1426899cWei Huang     */
6159242286c35743422051d439d7460cd0a1426899cWei Huang    public static final int MINIMUM_IMAGE_COMPRESSION_QUALITY = 50;
616bd09a4b8c2d1f922f1459c4d7b61e7e87ed4ddf3The Android Open Source Project
617f79b803adc0cee3778cf6aac52d203896cde5d95Christian Gustafsson    /**
618f79b803adc0cee3778cf6aac52d203896cde5d95Christian Gustafsson     * Message overhead that reduces the maximum image byte size.
619f79b803adc0cee3778cf6aac52d203896cde5d95Christian Gustafsson     * 5000 is a realistic overhead number that allows for user to also include
620f79b803adc0cee3778cf6aac52d203896cde5d95Christian Gustafsson     * a small MIDI file or a couple pages of text along with the picture.
621f79b803adc0cee3778cf6aac52d203896cde5d95Christian Gustafsson     */
622f79b803adc0cee3778cf6aac52d203896cde5d95Christian Gustafsson    public static final int MESSAGE_OVERHEAD = 5000;
623f79b803adc0cee3778cf6aac52d203896cde5d95Christian Gustafsson
62472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    public static void resizeImageAsync(final Context context,
62572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            final Uri imageUri, final Handler handler,
626edd39351defc331fc268a6ed88338f64fe6f17cfTom Taylor            final ResizeImageResultCallback cb,
627edd39351defc331fc268a6ed88338f64fe6f17cfTom Taylor            final boolean append) {
62872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
6291224b6560c48e146ee304f9c807296f6c22cdefbTom Taylor        // Show a progress toast if the resize hasn't finished
63072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // within one second.
63172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // Stash the runnable for showing it away so we can cancel
63272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // it later if the resize completes ahead of the deadline.
63372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        final Runnable showProgress = new Runnable() {
6341009d4bf5ee9fd1f2523e530828de5babb78eb19Todor Kalaydjiev            @Override
63572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            public void run() {
6361224b6560c48e146ee304f9c807296f6c22cdefbTom Taylor                Toast.makeText(context, R.string.compressing, Toast.LENGTH_SHORT).show();
63772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
63872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        };
63972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // Schedule it for one second from now.
64072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        handler.postDelayed(showProgress, 1000);
6419c5e0566f91c7622a7cf9d53a6a84c56ed4139c1Tom Taylor
64272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        new Thread(new Runnable() {
6431009d4bf5ee9fd1f2523e530828de5babb78eb19Todor Kalaydjiev            @Override
64472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            public void run() {
64572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                final PduPart part;
64672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                try {
64772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    UriImage image = new UriImage(context, imageUri);
6481009d4bf5ee9fd1f2523e530828de5babb78eb19Todor Kalaydjiev                    int widthLimit = MmsConfig.getMaxImageWidth();
6491009d4bf5ee9fd1f2523e530828de5babb78eb19Todor Kalaydjiev                    int heightLimit = MmsConfig.getMaxImageHeight();
6501009d4bf5ee9fd1f2523e530828de5babb78eb19Todor Kalaydjiev                    // In mms_config.xml, the max width has always been declared larger than the max
6511009d4bf5ee9fd1f2523e530828de5babb78eb19Todor Kalaydjiev                    // height. Swap the width and height limits if necessary so we scale the picture
6521009d4bf5ee9fd1f2523e530828de5babb78eb19Todor Kalaydjiev                    // as little as possible.
6531009d4bf5ee9fd1f2523e530828de5babb78eb19Todor Kalaydjiev                    if (image.getHeight() > image.getWidth()) {
6541009d4bf5ee9fd1f2523e530828de5babb78eb19Todor Kalaydjiev                        int temp = widthLimit;
6551009d4bf5ee9fd1f2523e530828de5babb78eb19Todor Kalaydjiev                        widthLimit = heightLimit;
6561009d4bf5ee9fd1f2523e530828de5babb78eb19Todor Kalaydjiev                        heightLimit = temp;
6571009d4bf5ee9fd1f2523e530828de5babb78eb19Todor Kalaydjiev                    }
6581009d4bf5ee9fd1f2523e530828de5babb78eb19Todor Kalaydjiev
65972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    part = image.getResizedImageAsPart(
6601009d4bf5ee9fd1f2523e530828de5babb78eb19Todor Kalaydjiev                        widthLimit,
6611009d4bf5ee9fd1f2523e530828de5babb78eb19Todor Kalaydjiev                        heightLimit,
662f79b803adc0cee3778cf6aac52d203896cde5d95Christian Gustafsson                        MmsConfig.getMaxMessageSize() - MESSAGE_OVERHEAD);
66372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                } finally {
6641224b6560c48e146ee304f9c807296f6c22cdefbTom Taylor                    // Cancel pending show of the progress toast if necessary.
66572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    handler.removeCallbacks(showProgress);
66672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                }
66772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
66872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                handler.post(new Runnable() {
6691009d4bf5ee9fd1f2523e530828de5babb78eb19Todor Kalaydjiev                    @Override
67072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    public void run() {
671edd39351defc331fc268a6ed88338f64fe6f17cfTom Taylor                        cb.onResizeResult(part, append);
67272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    }
67372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                });
67472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
675ddd31c4011b4191035bdfbba05a8edb1785f71afTodor Kalaydjiev        }, "MessageUtils.resizeImageAsync").start();
67672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
67772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
67872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    public static void showDiscardDraftConfirmDialog(Context context,
67972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            OnClickListener listener) {
68072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        new AlertDialog.Builder(context)
68172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                .setMessage(R.string.discard_message_reason)
68272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                .setPositiveButton(R.string.yes, listener)
68372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                .setNegativeButton(R.string.no, null)
68472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                .show();
68572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
68672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
68713dbe96fc54f9b7190fd415d737f9a56dc409d10Wei Huang    public static String getLocalNumber() {
68872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (null == sLocalNumber) {
689bb8edcae15a50b3651261db70791afc668aae294Tom Taylor            sLocalNumber = MmsApp.getApplication().getTelephonyManager().getLine1Number();
69072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
69172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        return sLocalNumber;
69272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
69372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
69472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    public static boolean isLocalNumber(String number) {
695f1bf432304bcc277397b028192eaf01a94c6417dWei Huang        if (number == null) {
696f1bf432304bcc277397b028192eaf01a94c6417dWei Huang            return false;
697f1bf432304bcc277397b028192eaf01a94c6417dWei Huang        }
698f1bf432304bcc277397b028192eaf01a94c6417dWei Huang
699f1bf432304bcc277397b028192eaf01a94c6417dWei Huang        // we don't use Mms.isEmailAddress() because it is too strict for comparing addresses like
700f1bf432304bcc277397b028192eaf01a94c6417dWei Huang        // "foo+caf_=6505551212=tmomail.net@gmail.com", which is the 'from' address from a forwarded email
701f1bf432304bcc277397b028192eaf01a94c6417dWei Huang        // message from Gmail. We don't want to treat "foo+caf_=6505551212=tmomail.net@gmail.com" and
702f1bf432304bcc277397b028192eaf01a94c6417dWei Huang        // "6505551212" to be the same.
703f1bf432304bcc277397b028192eaf01a94c6417dWei Huang        if (number.indexOf('@') >= 0) {
704b6a0383dc77efea9a48e43e4e21a4290e89bf0a4Wei Huang            return false;
705b6a0383dc77efea9a48e43e4e21a4290e89bf0a4Wei Huang        }
706b6a0383dc77efea9a48e43e4e21a4290e89bf0a4Wei Huang
70772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        return PhoneNumberUtils.compare(number, getLocalNumber());
70872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
70972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
71072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    public static void handleReadReport(final Context context,
711b04236e2977ac69e63cc0fa123399a584b606945Tom Taylor            final Collection<Long> threadIds,
71272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            final int status,
71372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            final Runnable callback) {
714b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor        StringBuilder selectionBuilder = new StringBuilder(Mms.MESSAGE_TYPE + " = "
715b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor                + PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF
716b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor                + " AND " + Mms.READ + " = 0"
717b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor                + " AND " + Mms.READ_REPORT + " = " + PduHeaders.VALUE_YES);
718b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor
719b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor        String[] selectionArgs = null;
720b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor        if (threadIds != null) {
721b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor            String threadIdSelection = null;
722b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor            StringBuilder buf = new StringBuilder();
723b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor            selectionArgs = new String[threadIds.size()];
724b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor            int i = 0;
725b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor
726b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor            for (long threadId : threadIds) {
727b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor                if (i > 0) {
728b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor                    buf.append(" OR ");
729b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor                }
730b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor                buf.append(Mms.THREAD_ID).append("=?");
731b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor                selectionArgs[i++] = Long.toString(threadId);
732b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor            }
733b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor            threadIdSelection = buf.toString();
73472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
735b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor            selectionBuilder.append(" AND (" + threadIdSelection + ")");
73672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
73772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
73872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        final Cursor c = SqliteWrapper.query(context, context.getContentResolver(),
73972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        Mms.Inbox.CONTENT_URI, new String[] {Mms._ID, Mms.MESSAGE_ID},
740b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor                        selectionBuilder.toString(), selectionArgs, null);
74172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
74272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (c == null) {
74372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            return;
74472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
74572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
74672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        final Map<String, String> map = new HashMap<String, String>();
74772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        try {
74872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            if (c.getCount() == 0) {
74972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                if (callback != null) {
75072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    callback.run();
75172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                }
75272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                return;
75372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
75472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
75572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            while (c.moveToNext()) {
75672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                Uri uri = ContentUris.withAppendedId(Mms.CONTENT_URI, c.getLong(0));
75772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                map.put(c.getString(1), AddressUtils.getFrom(context, uri));
75872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
75972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        } finally {
76072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            c.close();
76172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
76272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
76372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        OnClickListener positiveListener = new OnClickListener() {
7641009d4bf5ee9fd1f2523e530828de5babb78eb19Todor Kalaydjiev            @Override
76572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            public void onClick(DialogInterface dialog, int which) {
76672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                for (final Map.Entry<String, String> entry : map.entrySet()) {
76772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    MmsMessageSender.sendReadRec(context, entry.getValue(),
76872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                                 entry.getKey(), status);
76972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                }
77072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
77172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                if (callback != null) {
77272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    callback.run();
77372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                }
774c4a34a0ccd414e2bba937e8abd105a0383afff35Tom Taylor                dialog.dismiss();
77572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
77672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        };
77772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
77872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        OnClickListener negativeListener = new OnClickListener() {
7791009d4bf5ee9fd1f2523e530828de5babb78eb19Todor Kalaydjiev            @Override
78072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            public void onClick(DialogInterface dialog, int which) {
78172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                if (callback != null) {
78272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    callback.run();
78372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                }
784c4a34a0ccd414e2bba937e8abd105a0383afff35Tom Taylor                dialog.dismiss();
78572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
78672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        };
78772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
78872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        OnCancelListener cancelListener = new OnCancelListener() {
7891009d4bf5ee9fd1f2523e530828de5babb78eb19Todor Kalaydjiev            @Override
79072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            public void onCancel(DialogInterface dialog) {
79172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                if (callback != null) {
79272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    callback.run();
79372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                }
794c4a34a0ccd414e2bba937e8abd105a0383afff35Tom Taylor                dialog.dismiss();
79572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
79672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        };
79772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
79872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        confirmReadReportDialog(context, positiveListener,
79972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                         negativeListener,
80072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                         cancelListener);
80172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
80272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
80372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static void confirmReadReportDialog(Context context,
80472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            OnClickListener positiveListener, OnClickListener negativeListener,
80572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            OnCancelListener cancelListener) {
80672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        AlertDialog.Builder builder = new AlertDialog.Builder(context);
80772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        builder.setCancelable(true);
80872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        builder.setTitle(R.string.confirm);
80972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        builder.setMessage(R.string.message_send_read_report);
81072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        builder.setPositiveButton(R.string.yes, positiveListener);
81172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        builder.setNegativeButton(R.string.no, negativeListener);
81272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        builder.setOnCancelListener(cancelListener);
81372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        builder.show();
81472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
81572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
81672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    public static String extractEncStrFromCursor(Cursor cursor,
81772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            int columnRawBytes, int columnCharset) {
81872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        String rawBytes = cursor.getString(columnRawBytes);
81972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        int charset = cursor.getInt(columnCharset);
82072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
82172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (TextUtils.isEmpty(rawBytes)) {
82272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            return "";
82372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        } else if (charset == CharacterSets.ANY_CHARSET) {
82472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            return rawBytes;
82572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        } else {
82672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            return new EncodedStringValue(charset, PduPersister.getBytes(rawBytes)).getString();
82772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
82872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
82972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
83072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static String extractEncStr(Context context, EncodedStringValue value) {
83172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (value != null) {
83272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            return value.getString();
83372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        } else {
83472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            return "";
83572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
83672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
8379c5e0566f91c7622a7cf9d53a6a84c56ed4139c1Tom Taylor
83872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    public static ArrayList<String> extractUris(URLSpan[] spans) {
83972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        int size = spans.length;
84072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        ArrayList<String> accumulator = new ArrayList<String>();
84172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
84272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        for (int i = 0; i < size; i++) {
84372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            accumulator.add(spans[i].getURL());
84472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
84572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        return accumulator;
84672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
84772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
8484522cafe21816d43626b8ac42e1c5d3667212a97Ye Wen    /**
8494522cafe21816d43626b8ac42e1c5d3667212a97Ye Wen     * Play/view the message attachments.
8504522cafe21816d43626b8ac42e1c5d3667212a97Ye Wen     * TOOD: We need to save the draft before launching another activity to view the attachments.
8514522cafe21816d43626b8ac42e1c5d3667212a97Ye Wen     *       This is hacky though since we will do saveDraft twice and slow down the UI.
8524522cafe21816d43626b8ac42e1c5d3667212a97Ye Wen     *       We should pass the slideshow in intent extra to the view activity instead of
8534522cafe21816d43626b8ac42e1c5d3667212a97Ye Wen     *       asking it to read attachments from database.
854661957caeb3110ae3328a995edd467ceedc07a36Tom Taylor     * @param activity
8554522cafe21816d43626b8ac42e1c5d3667212a97Ye Wen     * @param msgUri the MMS message URI in database
8564522cafe21816d43626b8ac42e1c5d3667212a97Ye Wen     * @param slideshow the slideshow to save
8574522cafe21816d43626b8ac42e1c5d3667212a97Ye Wen     * @param persister the PDU persister for updating the database
8584522cafe21816d43626b8ac42e1c5d3667212a97Ye Wen     * @param sendReq the SendReq for updating the database
8594522cafe21816d43626b8ac42e1c5d3667212a97Ye Wen     */
860661957caeb3110ae3328a995edd467ceedc07a36Tom Taylor    public static void viewMmsMessageAttachment(Activity activity, Uri msgUri,
861661957caeb3110ae3328a995edd467ceedc07a36Tom Taylor            SlideshowModel slideshow, AsyncDialog asyncDialog) {
862661957caeb3110ae3328a995edd467ceedc07a36Tom Taylor        viewMmsMessageAttachment(activity, msgUri, slideshow, 0, asyncDialog);
8636767962317b959aa656c61741b1c1de4f9530f99Tom Taylor    }
8646767962317b959aa656c61741b1c1de4f9530f99Tom Taylor
865661957caeb3110ae3328a995edd467ceedc07a36Tom Taylor    public static void viewMmsMessageAttachment(final Activity activity, final Uri msgUri,
866661957caeb3110ae3328a995edd467ceedc07a36Tom Taylor            final SlideshowModel slideshow, final int requestCode, AsyncDialog asyncDialog) {
8674522cafe21816d43626b8ac42e1c5d3667212a97Ye Wen        boolean isSimple = (slideshow == null) ? false : slideshow.isSimple();
8684522cafe21816d43626b8ac42e1c5d3667212a97Ye Wen        if (isSimple) {
8694522cafe21816d43626b8ac42e1c5d3667212a97Ye Wen            // In attachment-editor mode, we only ever have one slide.
870661957caeb3110ae3328a995edd467ceedc07a36Tom Taylor            MessageUtils.viewSimpleSlideshow(activity, slideshow);
8714522cafe21816d43626b8ac42e1c5d3667212a97Ye Wen        } else {
872661957caeb3110ae3328a995edd467ceedc07a36Tom Taylor            // The user wants to view the slideshow. We have to persist the slideshow parts
873661957caeb3110ae3328a995edd467ceedc07a36Tom Taylor            // in a background task. If the task takes longer than a half second, a progress dialog
874661957caeb3110ae3328a995edd467ceedc07a36Tom Taylor            // is displayed. Once the PDU persisting is done, another runnable on the UI thread get
875661957caeb3110ae3328a995edd467ceedc07a36Tom Taylor            // executed to start the SlideshowActivity.
876661957caeb3110ae3328a995edd467ceedc07a36Tom Taylor            asyncDialog.runAsync(new Runnable() {
877661957caeb3110ae3328a995edd467ceedc07a36Tom Taylor                @Override
878661957caeb3110ae3328a995edd467ceedc07a36Tom Taylor                public void run() {
879661957caeb3110ae3328a995edd467ceedc07a36Tom Taylor                    // If a slideshow was provided, save it to disk first.
880661957caeb3110ae3328a995edd467ceedc07a36Tom Taylor                    if (slideshow != null) {
881661957caeb3110ae3328a995edd467ceedc07a36Tom Taylor                        PduPersister persister = PduPersister.getPduPersister(activity);
882661957caeb3110ae3328a995edd467ceedc07a36Tom Taylor                        try {
883661957caeb3110ae3328a995edd467ceedc07a36Tom Taylor                            PduBody pb = slideshow.toPduBody();
884469db72fcf219fd4c60bc9b01c728bdc3e866d40Tom Taylor                            persister.updateParts(msgUri, pb, null);
885661957caeb3110ae3328a995edd467ceedc07a36Tom Taylor                            slideshow.sync(pb);
886661957caeb3110ae3328a995edd467ceedc07a36Tom Taylor                        } catch (MmsException e) {
887661957caeb3110ae3328a995edd467ceedc07a36Tom Taylor                            Log.e(TAG, "Unable to save message for preview");
888661957caeb3110ae3328a995edd467ceedc07a36Tom Taylor                            return;
889661957caeb3110ae3328a995edd467ceedc07a36Tom Taylor                        }
890661957caeb3110ae3328a995edd467ceedc07a36Tom Taylor                    }
891b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick                }
892661957caeb3110ae3328a995edd467ceedc07a36Tom Taylor            }, new Runnable() {
893661957caeb3110ae3328a995edd467ceedc07a36Tom Taylor                @Override
894661957caeb3110ae3328a995edd467ceedc07a36Tom Taylor                public void run() {
895661957caeb3110ae3328a995edd467ceedc07a36Tom Taylor                    // Once the above background thread is complete, this runnable is run
896661957caeb3110ae3328a995edd467ceedc07a36Tom Taylor                    // on the UI thread to launch the slideshow activity.
897661957caeb3110ae3328a995edd467ceedc07a36Tom Taylor                    launchSlideshowActivity(activity, msgUri, requestCode);
898661957caeb3110ae3328a995edd467ceedc07a36Tom Taylor                }
899661957caeb3110ae3328a995edd467ceedc07a36Tom Taylor            }, R.string.building_slideshow_title);
9004522cafe21816d43626b8ac42e1c5d3667212a97Ye Wen        }
9014522cafe21816d43626b8ac42e1c5d3667212a97Ye Wen    }
9029c5e0566f91c7622a7cf9d53a6a84c56ed4139c1Tom Taylor
903661957caeb3110ae3328a995edd467ceedc07a36Tom Taylor    public static void launchSlideshowActivity(Context context, Uri msgUri, int requestCode) {
904661957caeb3110ae3328a995edd467ceedc07a36Tom Taylor        // Launch the slideshow activity to play/view.
905661957caeb3110ae3328a995edd467ceedc07a36Tom Taylor        Intent intent = new Intent(context, SlideshowActivity.class);
906661957caeb3110ae3328a995edd467ceedc07a36Tom Taylor        intent.setData(msgUri);
907661957caeb3110ae3328a995edd467ceedc07a36Tom Taylor        if (requestCode > 0 && context instanceof Activity) {
908661957caeb3110ae3328a995edd467ceedc07a36Tom Taylor            ((Activity)context).startActivityForResult(intent, requestCode);
909b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick        } else {
910661957caeb3110ae3328a995edd467ceedc07a36Tom Taylor            context.startActivity(intent);
911b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick        }
912661957caeb3110ae3328a995edd467ceedc07a36Tom Taylor
913b9bcfdd226bbb6f5b265f925343375192963d58aFicus Kirkpatrick    }
914812391ad832f3fdac054ad3a50af563da16e99b5Wei Huang
9159242286c35743422051d439d7460cd0a1426899cWei Huang    /**
9169242286c35743422051d439d7460cd0a1426899cWei Huang     * Debugging
9179242286c35743422051d439d7460cd0a1426899cWei Huang     */
9189242286c35743422051d439d7460cd0a1426899cWei Huang    public static void writeHprofDataToFile(){
919ebea1f24c246b8fa972ab9cbe52e6f506c5fc825Tom Taylor        String filename = Environment.getExternalStorageDirectory() + "/mms_oom_hprof_data";
9209242286c35743422051d439d7460cd0a1426899cWei Huang        try {
9219242286c35743422051d439d7460cd0a1426899cWei Huang            android.os.Debug.dumpHprofData(filename);
9229242286c35743422051d439d7460cd0a1426899cWei Huang            Log.i(TAG, "##### written hprof data to " + filename);
9239242286c35743422051d439d7460cd0a1426899cWei Huang        } catch (IOException ex) {
9249242286c35743422051d439d7460cd0a1426899cWei Huang            Log.e(TAG, "writeHprofDataToFile: caught " + ex);
9259242286c35743422051d439d7460cd0a1426899cWei Huang        }
9269242286c35743422051d439d7460cd0a1426899cWei Huang    }
9279242286c35743422051d439d7460cd0a1426899cWei Huang
928f4a44bba2c6a8cdaa4dd86d9dc4560775f8e0bc0Tom Taylor    // An alias (or commonly called "nickname") is:
929f4a44bba2c6a8cdaa4dd86d9dc4560775f8e0bc0Tom Taylor    // Nickname must begin with a letter.
930f4a44bba2c6a8cdaa4dd86d9dc4560775f8e0bc0Tom Taylor    // Only letters a-z, numbers 0-9, or . are allowed in Nickname field.
931817eb982a66303a8f87fc3061e3493a232627e96Satish Roddom    public static boolean isAlias(String string) {
932f6ddd0bb7fff9f479f6c306d3d3e154c6c533061Wei Huang        if (!MmsConfig.isAliasEnabled()) {
933f6ddd0bb7fff9f479f6c306d3d3e154c6c533061Wei Huang            return false;
934f6ddd0bb7fff9f479f6c306d3d3e154c6c533061Wei Huang        }
935f6ddd0bb7fff9f479f6c306d3d3e154c6c533061Wei Huang
936f4a44bba2c6a8cdaa4dd86d9dc4560775f8e0bc0Tom Taylor        int len = string == null ? 0 : string.length();
937b19f3b32bd202fa9f25a45e9e3068b33c12b70c0Tom Taylor
938f4a44bba2c6a8cdaa4dd86d9dc4560775f8e0bc0Tom Taylor        if (len < MmsConfig.getAliasMinChars() || len > MmsConfig.getAliasMaxChars()) {
939f6ddd0bb7fff9f479f6c306d3d3e154c6c533061Wei Huang            return false;
940f6ddd0bb7fff9f479f6c306d3d3e154c6c533061Wei Huang        }
941f6ddd0bb7fff9f479f6c306d3d3e154c6c533061Wei Huang
942f4a44bba2c6a8cdaa4dd86d9dc4560775f8e0bc0Tom Taylor        if (!Character.isLetter(string.charAt(0))) {    // Nickname begins with a letter
943f6ddd0bb7fff9f479f6c306d3d3e154c6c533061Wei Huang            return false;
944f6ddd0bb7fff9f479f6c306d3d3e154c6c533061Wei Huang        }
945f4a44bba2c6a8cdaa4dd86d9dc4560775f8e0bc0Tom Taylor        for (int i = 1; i < len; i++) {
946f4a44bba2c6a8cdaa4dd86d9dc4560775f8e0bc0Tom Taylor            char c = string.charAt(i);
947f4a44bba2c6a8cdaa4dd86d9dc4560775f8e0bc0Tom Taylor            if (!(Character.isLetterOrDigit(c) || c == '.')) {
948f4a44bba2c6a8cdaa4dd86d9dc4560775f8e0bc0Tom Taylor                return false;
94978f81825431c8c52cad57bc4a363747533a701abWei Huang            }
950817eb982a66303a8f87fc3061e3493a232627e96Satish Roddom        }
951f4a44bba2c6a8cdaa4dd86d9dc4560775f8e0bc0Tom Taylor
952817eb982a66303a8f87fc3061e3493a232627e96Satish Roddom        return true;
953817eb982a66303a8f87fc3061e3493a232627e96Satish Roddom    }
954817eb982a66303a8f87fc3061e3493a232627e96Satish Roddom
95578f81825431c8c52cad57bc4a363747533a701abWei Huang    /**
95678f81825431c8c52cad57bc4a363747533a701abWei Huang     * Given a phone number, return the string without syntactic sugar, meaning parens,
95778f81825431c8c52cad57bc4a363747533a701abWei Huang     * spaces, slashes, dots, dashes, etc. If the input string contains non-numeric
95878f81825431c8c52cad57bc4a363747533a701abWei Huang     * non-punctuation characters, return null.
95978f81825431c8c52cad57bc4a363747533a701abWei Huang     */
96078f81825431c8c52cad57bc4a363747533a701abWei Huang    private static String parsePhoneNumberForMms(String address) {
96178f81825431c8c52cad57bc4a363747533a701abWei Huang        StringBuilder builder = new StringBuilder();
96278f81825431c8c52cad57bc4a363747533a701abWei Huang        int len = address.length();
96378f81825431c8c52cad57bc4a363747533a701abWei Huang
96478f81825431c8c52cad57bc4a363747533a701abWei Huang        for (int i = 0; i < len; i++) {
96578f81825431c8c52cad57bc4a363747533a701abWei Huang            char c = address.charAt(i);
96678f81825431c8c52cad57bc4a363747533a701abWei Huang
96778f81825431c8c52cad57bc4a363747533a701abWei Huang            // accept the first '+' in the address
96878f81825431c8c52cad57bc4a363747533a701abWei Huang            if (c == '+' && builder.length() == 0) {
96978f81825431c8c52cad57bc4a363747533a701abWei Huang                builder.append(c);
97078f81825431c8c52cad57bc4a363747533a701abWei Huang                continue;
97178f81825431c8c52cad57bc4a363747533a701abWei Huang            }
97278f81825431c8c52cad57bc4a363747533a701abWei Huang
97378f81825431c8c52cad57bc4a363747533a701abWei Huang            if (Character.isDigit(c)) {
97478f81825431c8c52cad57bc4a363747533a701abWei Huang                builder.append(c);
97578f81825431c8c52cad57bc4a363747533a701abWei Huang                continue;
97678f81825431c8c52cad57bc4a363747533a701abWei Huang            }
97778f81825431c8c52cad57bc4a363747533a701abWei Huang
97878f81825431c8c52cad57bc4a363747533a701abWei Huang            if (numericSugarMap.get(c) == null) {
97978f81825431c8c52cad57bc4a363747533a701abWei Huang                return null;
98078f81825431c8c52cad57bc4a363747533a701abWei Huang            }
98178f81825431c8c52cad57bc4a363747533a701abWei Huang        }
98278f81825431c8c52cad57bc4a363747533a701abWei Huang        return builder.toString();
98378f81825431c8c52cad57bc4a363747533a701abWei Huang    }
98478f81825431c8c52cad57bc4a363747533a701abWei Huang
98578f81825431c8c52cad57bc4a363747533a701abWei Huang    /**
98678f81825431c8c52cad57bc4a363747533a701abWei Huang     * Returns true if the address passed in is a valid MMS address.
98778f81825431c8c52cad57bc4a363747533a701abWei Huang     */
98878f81825431c8c52cad57bc4a363747533a701abWei Huang    public static boolean isValidMmsAddress(String address) {
98978f81825431c8c52cad57bc4a363747533a701abWei Huang        String retVal = parseMmsAddress(address);
99078f81825431c8c52cad57bc4a363747533a701abWei Huang        return (retVal != null);
99178f81825431c8c52cad57bc4a363747533a701abWei Huang    }
99278f81825431c8c52cad57bc4a363747533a701abWei Huang
99378f81825431c8c52cad57bc4a363747533a701abWei Huang    /**
99478f81825431c8c52cad57bc4a363747533a701abWei Huang     * parse the input address to be a valid MMS address.
99578f81825431c8c52cad57bc4a363747533a701abWei Huang     * - if the address is an email address, leave it as is.
99678f81825431c8c52cad57bc4a363747533a701abWei Huang     * - if the address can be parsed into a valid MMS phone number, return the parsed number.
99778f81825431c8c52cad57bc4a363747533a701abWei Huang     * - if the address is a compliant alias address, leave it as is.
99878f81825431c8c52cad57bc4a363747533a701abWei Huang     */
99978f81825431c8c52cad57bc4a363747533a701abWei Huang    public static String parseMmsAddress(String address) {
100078f81825431c8c52cad57bc4a363747533a701abWei Huang        // if it's a valid Email address, use that.
100178f81825431c8c52cad57bc4a363747533a701abWei Huang        if (Mms.isEmailAddress(address)) {
100278f81825431c8c52cad57bc4a363747533a701abWei Huang            return address;
100378f81825431c8c52cad57bc4a363747533a701abWei Huang        }
100478f81825431c8c52cad57bc4a363747533a701abWei Huang
100578f81825431c8c52cad57bc4a363747533a701abWei Huang        // if we are able to parse the address to a MMS compliant phone number, take that.
100678f81825431c8c52cad57bc4a363747533a701abWei Huang        String retVal = parsePhoneNumberForMms(address);
100778f81825431c8c52cad57bc4a363747533a701abWei Huang        if (retVal != null) {
100878f81825431c8c52cad57bc4a363747533a701abWei Huang            return retVal;
100978f81825431c8c52cad57bc4a363747533a701abWei Huang        }
101078f81825431c8c52cad57bc4a363747533a701abWei Huang
101178f81825431c8c52cad57bc4a363747533a701abWei Huang        // if it's an alias compliant address, use that.
101278f81825431c8c52cad57bc4a363747533a701abWei Huang        if (isAlias(address)) {
101378f81825431c8c52cad57bc4a363747533a701abWei Huang            return address;
101478f81825431c8c52cad57bc4a363747533a701abWei Huang        }
101578f81825431c8c52cad57bc4a363747533a701abWei Huang
101678f81825431c8c52cad57bc4a363747533a701abWei Huang        // it's not a valid MMS address, return null
101778f81825431c8c52cad57bc4a363747533a701abWei Huang        return null;
101878f81825431c8c52cad57bc4a363747533a701abWei Huang    }
101978f81825431c8c52cad57bc4a363747533a701abWei Huang
1020812391ad832f3fdac054ad3a50af563da16e99b5Wei Huang    private static void log(String msg) {
1021812391ad832f3fdac054ad3a50af563da16e99b5Wei Huang        Log.d(TAG, "[MsgUtils] " + msg);
1022812391ad832f3fdac054ad3a50af563da16e99b5Wei Huang    }
102372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project}
1024