mirror of
https://github.com/oxen-io/session-android.git
synced 2025-10-24 15:31:46 +00:00
Support for dual-sim SMS/MMS functionality
Allow source selection for sending SMS/MMS, and display the SIM that received SMS/MMS. Fixes #555 Closes #5199 // FREEBIE
This commit is contained in:
@@ -9,9 +9,9 @@ import org.thoughtcrime.securesms.attachments.Attachment;
|
||||
import org.thoughtcrime.securesms.attachments.UriAttachment;
|
||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||
import org.thoughtcrime.securesms.crypto.MasterSecretUnion;
|
||||
import org.thoughtcrime.securesms.database.AttachmentDatabase;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.MmsDatabase;
|
||||
import org.thoughtcrime.securesms.database.AttachmentDatabase;
|
||||
import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement;
|
||||
import org.thoughtcrime.securesms.mms.ApnUnavailableException;
|
||||
import org.thoughtcrime.securesms.mms.CompatMmsConnection;
|
||||
@@ -35,7 +35,6 @@ import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import ws.com.google.android.mms.ContentType;
|
||||
import ws.com.google.android.mms.MmsException;
|
||||
import ws.com.google.android.mms.pdu.EncodedStringValue;
|
||||
import ws.com.google.android.mms.pdu.NotificationInd;
|
||||
@@ -75,8 +74,8 @@ public class MmsDownloadJob extends MasterSecretJob {
|
||||
|
||||
@Override
|
||||
public void onRun(MasterSecret masterSecret) {
|
||||
MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
|
||||
Optional<NotificationInd> notification = database.getNotification(messageId);
|
||||
MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
|
||||
Optional<Pair<NotificationInd, Integer>> notification = database.getNotification(messageId);
|
||||
|
||||
if (!notification.isPresent()) {
|
||||
Log.w(TAG, "No notification for ID: " + messageId);
|
||||
@@ -84,22 +83,24 @@ public class MmsDownloadJob extends MasterSecretJob {
|
||||
}
|
||||
|
||||
try {
|
||||
if (notification.get().getContentLocation() == null) {
|
||||
if (notification.get().first.getContentLocation() == null) {
|
||||
throw new MmsException("Notification content location was null.");
|
||||
}
|
||||
|
||||
database.markDownloadState(messageId, MmsDatabase.Status.DOWNLOAD_CONNECTING);
|
||||
|
||||
String contentLocation = new String(notification.get().getContentLocation());
|
||||
byte[] transactionId = notification.get().getTransactionId();
|
||||
String contentLocation = new String(notification.get().first.getContentLocation());
|
||||
byte[] transactionId = notification.get().first.getTransactionId();
|
||||
|
||||
Log.w(TAG, "Downloading mms at " + Uri.parse(contentLocation).getHost());
|
||||
|
||||
RetrieveConf retrieveConf = new CompatMmsConnection(context).retrieve(contentLocation, transactionId);
|
||||
RetrieveConf retrieveConf = new CompatMmsConnection(context).retrieve(contentLocation, transactionId, notification.get().second);
|
||||
|
||||
if (retrieveConf == null) {
|
||||
throw new MmsException("RetrieveConf was null");
|
||||
}
|
||||
storeRetrievedMms(masterSecret, contentLocation, messageId, threadId, retrieveConf);
|
||||
|
||||
storeRetrievedMms(masterSecret, contentLocation, messageId, threadId, retrieveConf, notification.get().second);
|
||||
} catch (ApnUnavailableException e) {
|
||||
Log.w(TAG, e);
|
||||
handleDownloadError(masterSecret, messageId, threadId, MmsDatabase.Status.DOWNLOAD_APN_UNAVAILABLE,
|
||||
@@ -146,7 +147,8 @@ public class MmsDownloadJob extends MasterSecretJob {
|
||||
}
|
||||
|
||||
private void storeRetrievedMms(MasterSecret masterSecret, String contentLocation,
|
||||
long messageId, long threadId, RetrieveConf retrieved)
|
||||
long messageId, long threadId, RetrieveConf retrieved,
|
||||
int subscriptionId)
|
||||
throws MmsException, NoSessionException, DuplicateMessageException, InvalidMessageException,
|
||||
LegacyMessageException
|
||||
{
|
||||
@@ -192,7 +194,7 @@ public class MmsDownloadJob extends MasterSecretJob {
|
||||
|
||||
|
||||
|
||||
IncomingMediaMessage message = new IncomingMediaMessage(from, to, cc, body, retrieved.getDate() * 1000L, attachments);
|
||||
IncomingMediaMessage message = new IncomingMediaMessage(from, to, cc, body, retrieved.getDate() * 1000L, attachments, subscriptionId);
|
||||
|
||||
Pair<Long, Long> messageAndThreadId = database.insertMessageInbox(new MasterSecretUnion(masterSecret),
|
||||
message, contentLocation, threadId);
|
||||
|
||||
@@ -19,16 +19,20 @@ import ws.com.google.android.mms.pdu.PduParser;
|
||||
|
||||
public class MmsReceiveJob extends ContextJob {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static final String TAG = MmsReceiveJob.class.getSimpleName();
|
||||
|
||||
private final byte[] data;
|
||||
private final int subscriptionId;
|
||||
|
||||
public MmsReceiveJob(Context context, byte[] data) {
|
||||
public MmsReceiveJob(Context context, byte[] data, int subscriptionId) {
|
||||
super(context, JobParameters.newBuilder()
|
||||
.withWakeLock(true)
|
||||
.withPersistence().create());
|
||||
|
||||
this.data = data;
|
||||
this.data = data;
|
||||
this.subscriptionId = subscriptionId;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -54,7 +58,7 @@ public class MmsReceiveJob extends ContextJob {
|
||||
|
||||
if (isNotification(pdu) && !isBlocked(pdu)) {
|
||||
MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
|
||||
Pair<Long, Long> messageAndThreadId = database.insertMessageInbox((NotificationInd)pdu);
|
||||
Pair<Long, Long> messageAndThreadId = database.insertMessageInbox((NotificationInd)pdu, subscriptionId);
|
||||
|
||||
Log.w(TAG, "Inserted received MMS notification...");
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@ import org.thoughtcrime.securesms.mms.MmsSendResult;
|
||||
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
|
||||
import org.thoughtcrime.securesms.mms.PartAuthority;
|
||||
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.transport.InsecureFallbackApprovalException;
|
||||
import org.thoughtcrime.securesms.transport.UndeliverableMessageException;
|
||||
@@ -25,12 +24,9 @@ import org.thoughtcrime.securesms.util.Hex;
|
||||
import org.thoughtcrime.securesms.util.NumberUtil;
|
||||
import org.thoughtcrime.securesms.util.SmilUtil;
|
||||
import org.thoughtcrime.securesms.util.TelephonyUtil;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.whispersystems.jobqueue.JobParameters;
|
||||
import org.whispersystems.jobqueue.requirements.NetworkRequirement;
|
||||
import org.whispersystems.textsecure.api.util.InvalidNumberException;
|
||||
import org.whispersystems.textsecure.api.util.PhoneNumberFormatter;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
@@ -83,7 +79,7 @@ public class MmsSendJob extends SendJob {
|
||||
validateDestinations(message, pdu);
|
||||
|
||||
final byte[] pduBytes = getPduBytes(pdu);
|
||||
final SendConf sendConf = new CompatMmsConnection(context).send(pduBytes);
|
||||
final SendConf sendConf = new CompatMmsConnection(context).send(pduBytes, message.getSubscriptionId());
|
||||
final MmsSendResult result = getSendResult(sendConf, pdu);
|
||||
|
||||
database.markAsSent(messageId);
|
||||
|
||||
@@ -261,7 +261,7 @@ public class PushDecryptJob extends ContextJob {
|
||||
MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
|
||||
String localNumber = TextSecurePreferences.getLocalNumber(context);
|
||||
IncomingMediaMessage mediaMessage = new IncomingMediaMessage(masterSecret, envelope.getSource(),
|
||||
localNumber, message.getTimestamp(),
|
||||
localNumber, message.getTimestamp(), -1,
|
||||
Optional.fromNullable(envelope.getRelay()),
|
||||
message.getBody(),
|
||||
message.getGroupInfo(),
|
||||
@@ -293,7 +293,7 @@ public class PushDecryptJob extends ContextJob {
|
||||
Recipients recipients = getSyncMessageDestination(message);
|
||||
OutgoingMediaMessage mediaMessage = new OutgoingMediaMessage(recipients, message.getMessage().getBody().orNull(),
|
||||
PointerAttachment.forPointers(masterSecret, message.getMessage().getAttachments()),
|
||||
message.getTimestamp(), ThreadDatabase.DistributionTypes.DEFAULT);
|
||||
message.getTimestamp(), -1, ThreadDatabase.DistributionTypes.DEFAULT);
|
||||
|
||||
mediaMessage = new OutgoingSecureMediaMessage(mediaMessage);
|
||||
|
||||
@@ -350,7 +350,7 @@ public class PushDecryptJob extends ContextJob {
|
||||
EncryptingSmsDatabase database = DatabaseFactory.getEncryptingSmsDatabase(context);
|
||||
Recipients recipients = getSyncMessageDestination(message);
|
||||
String body = message.getMessage().getBody().or("");
|
||||
OutgoingTextMessage outgoingTextMessage = new OutgoingTextMessage(recipients, body);
|
||||
OutgoingTextMessage outgoingTextMessage = new OutgoingTextMessage(recipients, body, -1);
|
||||
|
||||
long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipients);
|
||||
long messageId = database.insertMessageOutbox(masterSecret, threadId, outgoingTextMessage, false, message.getTimestamp());
|
||||
|
||||
@@ -23,17 +23,21 @@ import java.util.List;
|
||||
|
||||
public class SmsReceiveJob extends ContextJob {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static final String TAG = SmsReceiveJob.class.getSimpleName();
|
||||
|
||||
private final Object[] pdus;
|
||||
private final int subscriptionId;
|
||||
|
||||
public SmsReceiveJob(Context context, Object[] pdus) {
|
||||
public SmsReceiveJob(Context context, Object[] pdus, int subscriptionId) {
|
||||
super(context, JobParameters.newBuilder()
|
||||
.withPersistence()
|
||||
.withWakeLock(true)
|
||||
.create());
|
||||
|
||||
this.pdus = pdus;
|
||||
this.pdus = pdus;
|
||||
this.subscriptionId = subscriptionId;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -41,7 +45,7 @@ public class SmsReceiveJob extends ContextJob {
|
||||
|
||||
@Override
|
||||
public void onRun() {
|
||||
Optional<IncomingTextMessage> message = assembleMessageFragments(pdus);
|
||||
Optional<IncomingTextMessage> message = assembleMessageFragments(pdus, subscriptionId);
|
||||
MasterSecret masterSecret = KeyCachingService.getMasterSecret(context);
|
||||
|
||||
MasterSecretUnion masterSecretUnion;
|
||||
@@ -95,11 +99,11 @@ public class SmsReceiveJob extends ContextJob {
|
||||
return messageAndThreadId;
|
||||
}
|
||||
|
||||
private Optional<IncomingTextMessage> assembleMessageFragments(Object[] pdus) {
|
||||
private Optional<IncomingTextMessage> assembleMessageFragments(Object[] pdus, int subscriptionId) {
|
||||
List<IncomingTextMessage> messages = new LinkedList<>();
|
||||
|
||||
for (Object pdu : pdus) {
|
||||
messages.add(new IncomingTextMessage(SmsMessage.createFromPdu((byte[])pdu)));
|
||||
messages.add(new IncomingTextMessage(SmsMessage.createFromPdu((byte[])pdu), subscriptionId));
|
||||
}
|
||||
|
||||
if (messages.isEmpty()) {
|
||||
|
||||
@@ -4,6 +4,7 @@ import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.telephony.PhoneNumberUtils;
|
||||
import android.telephony.SmsManager;
|
||||
import android.util.Log;
|
||||
@@ -105,7 +106,7 @@ public class SmsSendJob extends SendJob {
|
||||
// catching it and marking the message as a failure. That way at least it doesn't
|
||||
// repeatedly crash every time you start the app.
|
||||
try {
|
||||
SmsManager.getDefault().sendMultipartTextMessage(recipient, null, messages, sentIntents, deliveredIntents);
|
||||
getSmsManagerFor(message.getSubscriptionId()).sendMultipartTextMessage(recipient, null, messages, sentIntents, deliveredIntents);
|
||||
} catch (NullPointerException npe) {
|
||||
Log.w(TAG, npe);
|
||||
Log.w(TAG, "Recipient: " + recipient);
|
||||
@@ -113,9 +114,9 @@ public class SmsSendJob extends SendJob {
|
||||
|
||||
try {
|
||||
for (int i=0;i<messages.size();i++) {
|
||||
SmsManager.getDefault().sendTextMessage(recipient, null, messages.get(i),
|
||||
sentIntents.get(i),
|
||||
deliveredIntents == null ? null : deliveredIntents.get(i));
|
||||
getSmsManagerFor(message.getSubscriptionId()).sendTextMessage(recipient, null, messages.get(i),
|
||||
sentIntents.get(i),
|
||||
deliveredIntents == null ? null : deliveredIntents.get(i));
|
||||
}
|
||||
} catch (NullPointerException npe2) {
|
||||
Log.w(TAG, npe);
|
||||
@@ -179,6 +180,14 @@ public class SmsSendJob extends SendJob {
|
||||
return pending;
|
||||
}
|
||||
|
||||
private SmsManager getSmsManagerFor(int subscriptionId) {
|
||||
if (Build.VERSION.SDK_INT >= 22 && subscriptionId != -1) {
|
||||
return SmsManager.getSmsManagerForSubscriptionId(subscriptionId);
|
||||
} else {
|
||||
return SmsManager.getDefault();
|
||||
}
|
||||
}
|
||||
|
||||
private static JobParameters constructParameters(Context context, String name) {
|
||||
JobParameters.Builder builder = JobParameters.newBuilder()
|
||||
.withPersistence()
|
||||
|
||||
Reference in New Issue
Block a user