1 /* 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.car.messenger.impl.datamodels.util; 18 19 import static android.provider.BaseColumns._ID; 20 import static android.provider.Telephony.BaseMmsColumns.CONTENT_TYPE; 21 22 import android.content.Context; 23 import android.database.Cursor; 24 import android.net.Uri; 25 import android.provider.Telephony; 26 import android.provider.Telephony.Mms.Addr; 27 import android.provider.Telephony.Mms.Part; 28 import android.provider.Telephony.Sms; 29 30 import androidx.annotation.NonNull; 31 32 import java.text.MessageFormat; 33 import java.time.Instant; 34 35 /** MMS Utils for parsing MMS Telephony Content */ 36 class MmsUtils { 37 38 @NonNull public static final String FORMAT_CONTENT_MMS_PART = "content://mms/{0}/part"; 39 @NonNull public static final String FORMAT_CONTENT_MMS_ADDR = "content://mms/{0}/addr"; 40 @NonNull public static final String FORMAT_TYPE_AND_MSG_ID = "type={0} AND msg_id={1}"; 41 42 /** MMS text messages come with extra characters and new lines that need to be removed */ 43 @NonNull private static final String REPLACE_CHARS = "\r\n"; 44 MmsUtils()45 private MmsUtils() {} 46 47 @NonNull static final String MMS_CONTENT_TYPE = "application/vnd.wap.multipart.related"; 48 private static final int ORIGINATOR_ADDRESS_TYPE = 137; 49 50 /** Returns true, if item on cursor position is an MMS message */ isMms(@onNull Cursor cursor)51 static Boolean isMms(@NonNull Cursor cursor) { 52 String contentType = cursor.getString(cursor.getColumnIndex(CONTENT_TYPE)); 53 return MMS_CONTENT_TYPE.equals(contentType); 54 } 55 56 /** 57 * Returns the parsed result as {link @MmsSmsMessage} 58 * 59 * @throws IllegalArgumentException if desired columns are missing. 60 * @see CursorUtils#CONTENT_CONVERSATION_PROJECTION 61 */ 62 @NonNull parseMms(@onNull Context context, @NonNull Cursor cursor)63 static MmsSmsMessage parseMms(@NonNull Context context, @NonNull Cursor cursor) { 64 MmsSmsMessage message = new MmsSmsMessage(); 65 message.mId = cursor.getString(cursor.getColumnIndex(_ID)); 66 message.mThreadId = cursor.getInt(cursor.getColumnIndex(Sms.THREAD_ID)); 67 message.mType = cursor.getInt(cursor.getColumnIndex(Telephony.Mms.MESSAGE_BOX)); 68 message.mSubscriptionId = cursor.getInt(cursor.getColumnIndex(Sms.SUBSCRIPTION_ID)); 69 message.mDate = Instant.ofEpochSecond(cursor.getLong(cursor.getColumnIndex(Sms.DATE))); 70 message.mRead = cursor.getInt(cursor.getColumnIndex(Sms.READ)) == 1; 71 message.mPhoneNumber = getOriginator(context, message.mId); 72 message.mBody = getMmsBody(context, message.mId); 73 return message; 74 } 75 getMmsBody(@onNull Context context, @NonNull String id)76 private static String getMmsBody(@NonNull Context context, @NonNull String id) { 77 String uriStr = MessageFormat.format(FORMAT_CONTENT_MMS_PART, id); 78 Uri uriAddress = Uri.parse(uriStr); 79 Cursor cursor = CursorUtils.simpleQuery(context, uriAddress); 80 StringBuilder stringBuilder = new StringBuilder(); 81 while (cursor != null && cursor.moveToNext()) { 82 stringBuilder.append(cursor.getString(cursor.getColumnIndex(Part.TEXT))); 83 stringBuilder.append(" "); 84 } 85 return stringBuilder.toString().replace(REPLACE_CHARS, ""); 86 } 87 88 @NonNull getOriginator(@onNull Context context, @NonNull String id)89 private static String getOriginator(@NonNull Context context, @NonNull String id) { 90 String selection = 91 MessageFormat.format(FORMAT_TYPE_AND_MSG_ID, ORIGINATOR_ADDRESS_TYPE, id); 92 String uriStr = MessageFormat.format(FORMAT_CONTENT_MMS_ADDR, id); 93 Cursor cursor = CursorUtils.simpleQueryWithSelection(context, Uri.parse(uriStr), selection); 94 String phoneNum = ""; 95 if (cursor != null && cursor.moveToFirst()) { 96 cursor.moveToFirst(); 97 phoneNum = cursor.getString(cursor.getColumnIndex(Addr.ADDRESS)); 98 cursor.close(); 99 } 100 return phoneNum; 101 } 102 } 103