Search in sources :

Example 1 with GenericPdu

use of com.google.android.mms.pdu.GenericPdu in project android-aosp-mms by slvn.

the class MessagingNotification method addMmsNotificationInfos.

private static final void addMmsNotificationInfos(Context context, Set<Long> threads, SortedSet<NotificationInfo> notificationSet) {
    ContentResolver resolver = context.getContentResolver();
    // This query looks like this when logged:
    // I/Database(  147): elapsedTime4Sql|/data/data/com.android.providers.telephony/databases/
    // mmssms.db|0.362 ms|SELECT thread_id, date, _id, sub, sub_cs FROM pdu WHERE ((msg_box=1
    // AND seen=0 AND (m_type=130 OR m_type=132))) ORDER BY date desc
    Cursor cursor = SqliteWrapper.query(context, resolver, Mms.CONTENT_URI, MMS_STATUS_PROJECTION, NEW_INCOMING_MM_CONSTRAINT, null, Mms.DATE + " desc");
    if (cursor == null) {
        return;
    }
    try {
        while (cursor.moveToNext()) {
            long msgId = cursor.getLong(COLUMN_MMS_ID);
            Uri msgUri = Mms.CONTENT_URI.buildUpon().appendPath(Long.toString(msgId)).build();
            String address = AddressUtils.getFrom(context, msgUri);
            Contact contact = Contact.get(address, false);
            if (contact.getSendToVoicemail()) {
                // don't notify, skip this one
                continue;
            }
            String subject = getMmsSubject(cursor.getString(COLUMN_SUBJECT), cursor.getInt(COLUMN_SUBJECT_CS));
            subject = MessageUtils.cleanseMmsSubject(context, subject);
            long threadId = cursor.getLong(COLUMN_THREAD_ID);
            long timeMillis = cursor.getLong(COLUMN_DATE) * 1000;
            if (Log.isLoggable(LogTag.APP, Log.VERBOSE)) {
                Log.d(TAG, "addMmsNotificationInfos: count=" + cursor.getCount() + ", addr = " + address + ", thread_id=" + threadId);
            }
            // Extract the message and/or an attached picture from the first slide
            Bitmap attachedPicture = null;
            String messageBody = null;
            int attachmentType = WorkingMessage.TEXT;
            try {
                GenericPdu pdu = sPduPersister.load(msgUri);
                if (pdu != null && pdu instanceof MultimediaMessagePdu) {
                    SlideshowModel slideshow = SlideshowModel.createFromPduBody(context, ((MultimediaMessagePdu) pdu).getBody());
                    attachmentType = getAttachmentType(slideshow);
                    SlideModel firstSlide = slideshow.get(0);
                    if (firstSlide != null) {
                        if (firstSlide.hasImage()) {
                            int maxDim = dp2Pixels(MAX_BITMAP_DIMEN_DP);
                            attachedPicture = firstSlide.getImage().getBitmap(maxDim, maxDim);
                        }
                        if (firstSlide.hasText()) {
                            messageBody = firstSlide.getText().getText();
                        }
                    }
                }
            } catch (final MmsException e) {
                Log.e(TAG, "MmsException loading uri: " + msgUri, e);
                // skip this bad boy -- don't generate an empty notification
                continue;
            }
            NotificationInfo info = getNewMessageNotificationInfo(context, false, /* isSms */
            address, messageBody, subject, threadId, timeMillis, attachedPicture, contact, attachmentType);
            notificationSet.add(info);
            threads.add(threadId);
        }
    } finally {
        cursor.close();
    }
}
Also used : MultimediaMessagePdu(com.google.android.mms.pdu.MultimediaMessagePdu) SpannableString(android.text.SpannableString) Cursor(android.database.Cursor) Uri(android.net.Uri) ContentResolver(android.content.ContentResolver) Contact(com.android.mms.data.Contact) Bitmap(android.graphics.Bitmap) MmsException(com.google.android.mms.MmsException) SlideshowModel(com.android.mms.model.SlideshowModel) GenericPdu(com.google.android.mms.pdu.GenericPdu) SlideModel(com.android.mms.model.SlideModel)

Example 2 with GenericPdu

use of com.google.android.mms.pdu.GenericPdu in project android-aosp-mms by slvn.

the class MmsMessageSender method sendMessage.

public boolean sendMessage(long token) throws MmsException {
    // Load the MMS from the message uri
    if (Log.isLoggable(LogTag.APP, Log.VERBOSE)) {
        LogTag.debug("sendMessage uri: " + mMessageUri);
    }
    PduPersister p = PduPersister.getPduPersister(mContext);
    GenericPdu pdu = p.load(mMessageUri);
    if (pdu.getMessageType() != PduHeaders.MESSAGE_TYPE_SEND_REQ) {
        throw new MmsException("Invalid message: " + pdu.getMessageType());
    }
    SendReq sendReq = (SendReq) pdu;
    // Update headers.
    updatePreferencesHeaders(sendReq);
    // MessageClass.
    sendReq.setMessageClass(DEFAULT_MESSAGE_CLASS.getBytes());
    // Update the 'date' field of the message before sending it.
    sendReq.setDate(System.currentTimeMillis() / 1000L);
    sendReq.setMessageSize(mMessageSize);
    p.updateHeaders(mMessageUri, sendReq);
    long messageId = ContentUris.parseId(mMessageUri);
    // Move the message into MMS Outbox.
    if (!mMessageUri.toString().startsWith(Mms.Draft.CONTENT_URI.toString())) {
        // If the message is already in the outbox (most likely because we created a "primed"
        // message in the outbox when the user hit send), then we have to manually put an
        // entry in the pending_msgs table which is where TransacationService looks for
        // messages to send. Normally, the entry in pending_msgs is created by the trigger:
        // insert_mms_pending_on_update, when a message is moved from drafts to the outbox.
        ContentValues values = new ContentValues(7);
        values.put(PendingMessages.PROTO_TYPE, MmsSms.MMS_PROTO);
        values.put(PendingMessages.MSG_ID, messageId);
        values.put(PendingMessages.MSG_TYPE, pdu.getMessageType());
        values.put(PendingMessages.ERROR_TYPE, 0);
        values.put(PendingMessages.ERROR_CODE, 0);
        values.put(PendingMessages.RETRY_INDEX, 0);
        values.put(PendingMessages.DUE_TIME, 0);
        SqliteWrapper.insert(mContext, mContext.getContentResolver(), PendingMessages.CONTENT_URI, values);
    } else {
        p.move(mMessageUri, Mms.Outbox.CONTENT_URI);
    }
    // Start MMS transaction service
    SendingProgressTokenManager.put(messageId, token);
    mContext.startService(new Intent(mContext, TransactionService.class));
    return true;
}
Also used : ContentValues(android.content.ContentValues) MmsException(com.google.android.mms.MmsException) PduPersister(com.google.android.mms.pdu.PduPersister) GenericPdu(com.google.android.mms.pdu.GenericPdu) Intent(android.content.Intent) SendReq(com.google.android.mms.pdu.SendReq)

Example 3 with GenericPdu

use of com.google.android.mms.pdu.GenericPdu in project android_frameworks_opt_telephony by LineageOS.

the class WapPushOverSms method decodeWapPdu.

/**
 * Decodes the wap push pdu. The decoded result is wrapped inside the {@link DecodedResult}
 * object. The caller of this method should check {@link DecodedResult#statusCode} for the
 * decoding status. It  can have the following values.
 *
 * Activity.RESULT_OK - the wap push pdu is successfully decoded and should be further processed
 * Intents.RESULT_SMS_HANDLED - the wap push pdu should be ignored.
 * Intents.RESULT_SMS_GENERIC_ERROR - the pdu is invalid.
 */
private DecodedResult decodeWapPdu(byte[] pdu, InboundSmsHandler handler) {
    DecodedResult result = new DecodedResult();
    if (DBG)
        Rlog.d(TAG, "Rx: " + IccUtils.bytesToHexString(pdu));
    try {
        int index = 0;
        int transactionId = pdu[index++] & 0xFF;
        int pduType = pdu[index++] & 0xFF;
        // Should we "abort" if no subId for now just no supplying extra param below
        int phoneId = handler.getPhone().getPhoneId();
        if ((pduType != WspTypeDecoder.PDU_TYPE_PUSH) && (pduType != WspTypeDecoder.PDU_TYPE_CONFIRMED_PUSH)) {
            index = mContext.getResources().getInteger(com.android.internal.R.integer.config_valid_wappush_index);
            if (index != -1) {
                transactionId = pdu[index++] & 0xff;
                pduType = pdu[index++] & 0xff;
                if (DBG)
                    Rlog.d(TAG, "index = " + index + " PDU Type = " + pduType + " transactionID = " + transactionId);
                // recheck wap push pduType
                if ((pduType != WspTypeDecoder.PDU_TYPE_PUSH) && (pduType != WspTypeDecoder.PDU_TYPE_CONFIRMED_PUSH)) {
                    if (DBG)
                        Rlog.w(TAG, "Received non-PUSH WAP PDU. Type = " + pduType);
                    result.statusCode = Intents.RESULT_SMS_HANDLED;
                    return result;
                }
            } else {
                if (DBG)
                    Rlog.w(TAG, "Received non-PUSH WAP PDU. Type = " + pduType);
                result.statusCode = Intents.RESULT_SMS_HANDLED;
                return result;
            }
        }
        WspTypeDecoder pduDecoder = TelephonyComponentFactory.getInstance().inject(WspTypeDecoder.class.getName()).makeWspTypeDecoder(pdu);
        /**
         * Parse HeaderLen(unsigned integer).
         * From wap-230-wsp-20010705-a section 8.1.2
         * The maximum size of a uintvar is 32 bits.
         * So it will be encoded in no more than 5 octets.
         */
        if (pduDecoder.decodeUintvarInteger(index) == false) {
            if (DBG)
                Rlog.w(TAG, "Received PDU. Header Length error.");
            result.statusCode = Intents.RESULT_SMS_GENERIC_ERROR;
            return result;
        }
        int headerLength = (int) pduDecoder.getValue32();
        index += pduDecoder.getDecodedDataLength();
        int headerStartIndex = index;
        /**
         * Parse Content-Type.
         * From wap-230-wsp-20010705-a section 8.4.2.24
         *
         * Content-type-value = Constrained-media | Content-general-form
         * Content-general-form = Value-length Media-type
         * Media-type = (Well-known-media | Extension-Media) *(Parameter)
         * Value-length = Short-length | (Length-quote Length)
         * Short-length = <Any octet 0-30>   (octet <= WAP_PDU_SHORT_LENGTH_MAX)
         * Length-quote = <Octet 31>         (WAP_PDU_LENGTH_QUOTE)
         * Length = Uintvar-integer
         */
        if (pduDecoder.decodeContentType(index) == false) {
            if (DBG)
                Rlog.w(TAG, "Received PDU. Header Content-Type error.");
            result.statusCode = Intents.RESULT_SMS_GENERIC_ERROR;
            return result;
        }
        String mimeType = pduDecoder.getValueString();
        long binaryContentType = pduDecoder.getValue32();
        index += pduDecoder.getDecodedDataLength();
        byte[] header = new byte[headerLength];
        System.arraycopy(pdu, headerStartIndex, header, 0, header.length);
        byte[] intentData;
        if (mimeType != null && mimeType.equals(WspTypeDecoder.CONTENT_TYPE_B_PUSH_CO)) {
            intentData = pdu;
        } else {
            int dataIndex = headerStartIndex + headerLength;
            intentData = new byte[pdu.length - dataIndex];
            System.arraycopy(pdu, dataIndex, intentData, 0, intentData.length);
        }
        int[] subIds = SubscriptionManager.getSubId(phoneId);
        int subId = (subIds != null) && (subIds.length > 0) ? subIds[0] : SmsManager.getDefaultSmsSubscriptionId();
        // Continue if PDU parsing fails: the default messaging app may successfully parse the
        // same PDU.
        GenericPdu parsedPdu = null;
        try {
            parsedPdu = new PduParser(intentData, shouldParseContentDisposition(subId)).parse();
        } catch (Exception e) {
            Rlog.e(TAG, "Unable to parse PDU: " + e.toString());
        }
        if (parsedPdu != null && parsedPdu.getMessageType() == MESSAGE_TYPE_NOTIFICATION_IND) {
            final NotificationInd nInd = (NotificationInd) parsedPdu;
            if (nInd.getFrom() != null && BlockChecker.isBlocked(mContext, nInd.getFrom().getString(), null)) {
                result.statusCode = Intents.RESULT_SMS_HANDLED;
                return result;
            }
        }
        /**
         * Seek for application ID field in WSP header.
         * If application ID is found, WapPushManager substitute the message
         * processing. Since WapPushManager is optional module, if WapPushManager
         * is not found, legacy message processing will be continued.
         */
        if (pduDecoder.seekXWapApplicationId(index, index + headerLength - 1)) {
            index = (int) pduDecoder.getValue32();
            pduDecoder.decodeXWapApplicationId(index);
            String wapAppId = pduDecoder.getValueString();
            if (wapAppId == null) {
                wapAppId = Integer.toString((int) pduDecoder.getValue32());
            }
            result.wapAppId = wapAppId;
            String contentType = ((mimeType == null) ? Long.toString(binaryContentType) : mimeType);
            result.contentType = contentType;
            if (DBG)
                Rlog.v(TAG, "appid found: " + wapAppId + ":" + contentType);
        }
        result.subId = subId;
        result.phoneId = phoneId;
        result.parsedPdu = parsedPdu;
        result.mimeType = mimeType;
        result.transactionId = transactionId;
        result.pduType = pduType;
        result.header = header;
        result.intentData = intentData;
        result.contentTypeParameters = pduDecoder.getContentParameters();
        result.statusCode = Activity.RESULT_OK;
    } catch (ArrayIndexOutOfBoundsException aie) {
        // 0-byte WAP PDU or other unexpected WAP PDU contents can easily throw this;
        // log exception string without stack trace and return false.
        Rlog.e(TAG, "ignoring dispatchWapPdu() array index exception: " + aie);
        result.statusCode = Intents.RESULT_SMS_GENERIC_ERROR;
    }
    return result;
}
Also used : PduParser(com.google.android.mms.pdu.PduParser) NotificationInd(com.google.android.mms.pdu.NotificationInd) GenericPdu(com.google.android.mms.pdu.GenericPdu) MmsException(com.google.android.mms.MmsException) RemoteException(android.os.RemoteException) SQLiteException(android.database.sqlite.SQLiteException)

Example 4 with GenericPdu

use of com.google.android.mms.pdu.GenericPdu in project android-aosp-mms by slvn.

the class NotificationTransaction method run.

public void run() {
    DownloadManager downloadManager = DownloadManager.getInstance();
    boolean autoDownload = allowAutoDownload();
    try {
        if (LOCAL_LOGV) {
            Log.v(TAG, "Notification transaction launched: " + this);
        }
        // By default, we set status to STATUS_DEFERRED because we
        // should response MMSC with STATUS_DEFERRED when we cannot
        // download a MM immediately.
        int status = STATUS_DEFERRED;
        // Don't try to download when data is suspended, as it will fail, so defer download
        if (!autoDownload) {
            downloadManager.markState(mUri, DownloadManager.STATE_UNSTARTED);
            sendNotifyRespInd(status);
            return;
        }
        downloadManager.markState(mUri, DownloadManager.STATE_DOWNLOADING);
        if (LOCAL_LOGV) {
            Log.v(TAG, "Content-Location: " + mContentLocation);
        }
        byte[] retrieveConfData = null;
        // with STATUS_DEFERRED.
        try {
            retrieveConfData = getPdu(mContentLocation);
        } catch (IOException e) {
            mTransactionState.setState(FAILED);
        }
        if (retrieveConfData != null) {
            GenericPdu pdu = new PduParser(retrieveConfData).parse();
            if ((pdu == null) || (pdu.getMessageType() != MESSAGE_TYPE_RETRIEVE_CONF)) {
                Log.e(TAG, "Invalid M-RETRIEVE.CONF PDU. " + (pdu != null ? "message type: " + pdu.getMessageType() : "null pdu"));
                mTransactionState.setState(FAILED);
                status = STATUS_UNRECOGNIZED;
            } else {
                // Save the received PDU (must be a M-RETRIEVE.CONF).
                PduPersister p = PduPersister.getPduPersister(mContext);
                Uri uri = p.persist(pdu, Inbox.CONTENT_URI, true, MessagingPreferenceActivity.getIsGroupMmsEnabled(mContext), null);
                // Use local time instead of PDU time
                ContentValues values = new ContentValues(1);
                values.put(Mms.DATE, System.currentTimeMillis() / 1000L);
                SqliteWrapper.update(mContext, mContext.getContentResolver(), uri, values, null, null);
                // We have successfully downloaded the new MM. Delete the
                // M-NotifyResp.ind from Inbox.
                SqliteWrapper.delete(mContext, mContext.getContentResolver(), mUri, null, null);
                Log.v(TAG, "NotificationTransaction received new mms message: " + uri);
                // Delete obsolete threads
                SqliteWrapper.delete(mContext, mContext.getContentResolver(), Threads.OBSOLETE_THREADS_URI, null, null);
                // Notify observers with newly received MM.
                mUri = uri;
                status = STATUS_RETRIEVED;
            }
        }
        if (LOCAL_LOGV) {
            Log.v(TAG, "status=0x" + Integer.toHexString(status));
        }
        // Check the status and update the result state of this Transaction.
        switch(status) {
            case STATUS_RETRIEVED:
                mTransactionState.setState(SUCCESS);
                break;
            case STATUS_DEFERRED:
                // STATUS_DEFERRED, may be a failed immediate retrieval.
                if (mTransactionState.getState() == INITIALIZED) {
                    mTransactionState.setState(SUCCESS);
                }
                break;
        }
        sendNotifyRespInd(status);
        // Make sure this thread isn't over the limits in message count.
        Recycler.getMmsRecycler().deleteOldMessagesInSameThreadAsMessage(mContext, mUri);
        MmsWidgetProvider.notifyDatasetChanged(mContext);
    } catch (Throwable t) {
        Log.e(TAG, Log.getStackTraceString(t));
    } finally {
        mTransactionState.setContentUri(mUri);
        if (!autoDownload) {
            // Always mark the transaction successful for deferred
            // download since any error here doesn't make sense.
            mTransactionState.setState(SUCCESS);
        }
        if (mTransactionState.getState() != SUCCESS) {
            mTransactionState.setState(FAILED);
            Log.e(TAG, "NotificationTransaction failed.");
        }
        notifyObservers();
    }
}
Also used : ContentValues(android.content.ContentValues) PduParser(com.google.android.mms.pdu.PduParser) PduPersister(com.google.android.mms.pdu.PduPersister) GenericPdu(com.google.android.mms.pdu.GenericPdu) IOException(java.io.IOException) DownloadManager(com.android.mms.util.DownloadManager) Uri(android.net.Uri)

Example 5 with GenericPdu

use of com.google.android.mms.pdu.GenericPdu in project android-aosp-mms by slvn.

the class SlideshowModel method getPduBody.

public static PduBody getPduBody(Context context, Uri msg) throws MmsException {
    PduPersister p = PduPersister.getPduPersister(context);
    GenericPdu pdu = p.load(msg);
    int msgType = pdu.getMessageType();
    if ((msgType == PduHeaders.MESSAGE_TYPE_SEND_REQ) || (msgType == PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF)) {
        return ((MultimediaMessagePdu) pdu).getBody();
    } else {
        throw new MmsException();
    }
}
Also used : MmsException(com.google.android.mms.MmsException) PduPersister(com.google.android.mms.pdu.PduPersister) GenericPdu(com.google.android.mms.pdu.GenericPdu) MultimediaMessagePdu(com.google.android.mms.pdu.MultimediaMessagePdu)

Aggregations

GenericPdu (com.google.android.mms.pdu.GenericPdu)5 MmsException (com.google.android.mms.MmsException)4 PduPersister (com.google.android.mms.pdu.PduPersister)3 ContentValues (android.content.ContentValues)2 Uri (android.net.Uri)2 MultimediaMessagePdu (com.google.android.mms.pdu.MultimediaMessagePdu)2 PduParser (com.google.android.mms.pdu.PduParser)2 ContentResolver (android.content.ContentResolver)1 Intent (android.content.Intent)1 Cursor (android.database.Cursor)1 SQLiteException (android.database.sqlite.SQLiteException)1 Bitmap (android.graphics.Bitmap)1 RemoteException (android.os.RemoteException)1 SpannableString (android.text.SpannableString)1 Contact (com.android.mms.data.Contact)1 SlideModel (com.android.mms.model.SlideModel)1 SlideshowModel (com.android.mms.model.SlideshowModel)1 DownloadManager (com.android.mms.util.DownloadManager)1 NotificationInd (com.google.android.mms.pdu.NotificationInd)1 SendReq (com.google.android.mms.pdu.SendReq)1